Files
LehrerApp/LehrerApp.Tests/BackupServiceTests.cs
T
adminandClaude Sonnet 5 48d07a2b99 Datensicherheit: Backup, Verschlüsselung, App-Sperre (Kapitel 13.3)
Automatisches rollierendes Backup der Datenbank beim Start mit
Wiederherstellung über die Einstellungen, versionierte Schema-Migration,
optionale Passwort-Verschlüsselung der LiteDB-Datei und eine App-Sperre
nach Inaktivität mit eigenem Passwort.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 13:07:36 +02:00

104 lines
3.3 KiB
C#

using LehrerApp.Core.Services;
using Xunit;
namespace LehrerApp.Tests;
public sealed class BackupServiceTests
{
[Fact]
public void CreateBackup_OhneVorhandeneDatenbank_GibtNullZurueck()
{
using var temp = new TempAppData();
var service = new BackupService(temp.Path);
var result = service.CreateBackup(Path.Combine(temp.Path, "fehlt.db"));
Assert.Null(result);
}
[Fact]
public void CreateBackup_KopiertDieDatenbankdatei()
{
using var temp = new TempAppData();
var dbPath = Path.Combine(temp.Path, "lehrerapp.db");
File.WriteAllText(dbPath, "Testinhalt");
var service = new BackupService(temp.Path);
var backupPath = service.CreateBackup(dbPath);
Assert.NotNull(backupPath);
Assert.True(File.Exists(backupPath));
Assert.Equal("Testinhalt", File.ReadAllText(backupPath!));
}
[Fact]
public void ListBackups_SortiertNeuesteZuerst()
{
using var temp = new TempAppData();
var dbPath = Path.Combine(temp.Path, "lehrerapp.db");
File.WriteAllText(dbPath, "v1");
var service = new BackupService(temp.Path);
var first = service.CreateBackup(dbPath)!;
File.SetLastWriteTime(first, DateTime.Now.AddMinutes(-5));
File.WriteAllText(dbPath, "v2");
var second = service.CreateBackup(dbPath)!;
var backups = service.ListBackups();
Assert.Equal(2, backups.Count);
Assert.Equal(second, backups[0].Path);
}
[Fact]
public void CreateBackup_BehaeltNurDieLetztenNBackups()
{
using var temp = new TempAppData();
var dbPath = Path.Combine(temp.Path, "lehrerapp.db");
var service = new BackupService(temp.Path);
for (var i = 0; i < 5; i++)
{
File.WriteAllText(dbPath, $"v{i}");
var backup = service.CreateBackup(dbPath, keepCount: 3)!;
File.SetLastWriteTime(backup, DateTime.Now.AddMinutes(-5 + i));
}
Assert.Equal(3, service.ListBackups().Count);
}
[Fact]
public void RestoreBackup_KopiertBackupUeberDieZieldatei()
{
using var temp = new TempAppData();
var dbPath = Path.Combine(temp.Path, "lehrerapp.db");
File.WriteAllText(dbPath, "alt");
var service = new BackupService(temp.Path);
var backupPath = service.CreateBackup(dbPath)!;
File.WriteAllText(dbPath, "neu-kaputt");
service.RestoreBackup(backupPath, dbPath);
Assert.Equal("alt", File.ReadAllText(dbPath));
}
[Fact]
public void RestoreBackup_OhneVorhandenesBackup_WirftException()
{
using var temp = new TempAppData();
var service = new BackupService(temp.Path);
Assert.Throws<FileNotFoundException>(() =>
service.RestoreBackup(Path.Combine(temp.Path, "backups", "fehlt.db"), Path.Combine(temp.Path, "lehrerapp.db")));
}
private sealed class TempAppData : IDisposable
{
public string Path { get; } = System.IO.Path.Combine(
System.IO.Path.GetTempPath(), $"lehrerapp-backup-tests-{Guid.NewGuid():N}");
public TempAppData() => Directory.CreateDirectory(Path);
public void Dispose() { if (Directory.Exists(Path)) Directory.Delete(Path, recursive: true); }
}
}