Testabdeckung Kapitel 13.1 (Tests, Fehlerbehandlung)
Vier neue xUnit-Testprojekte (LehrerApp.Tests, .Data.Tests, .Desktop.Tests, .Sync.Tests) mit zusammen 104 Tests: GradingService, SchoolYearService, Repositories gegen In-Memory-LiteDB, Mitarbeits-Aggregation (3.2), Zeugnisnotenberechnung (2.4) und ConflictResolver. Dabei zwei echte Fehler in der Sync-Schicht gefunden und behoben: - SyncEvent.EventId fehlte [BsonId], wodurch EventQueue.Acknowledge() nie etwas aus der Queue löschte. - ConflictResolver verglich Zeitstempel unterschiedlicher DateTimeKind direkt (LiteDB liefert Local statt Utc zurück), was die Gleichstand- Regel außerhalb von UTC+0 verfälschte. SchoolYearService.CurrentSchoolYear()/RecentSchoolYears() um ein optionales today-Argument erweitert, um den Schuljahreswechsel deterministisch zu testen; LiteDbContext um einen Stream-Konstruktor für In-Memory-Tests.
This commit is contained in:
@@ -20,7 +20,12 @@ public class ConflictResolver(EventQueue queue)
|
||||
{
|
||||
(DeviceType.Desktop, DeviceType.Companion) => local,
|
||||
(DeviceType.Companion, DeviceType.Desktop) => remote,
|
||||
_ => local.Timestamp >= remote.Timestamp ? local : remote,
|
||||
// ToUniversalTime(): LiteDB liefert DateTime beim Auslesen aus der Queue als Kind=Local
|
||||
// zurück (Ticks werden dabei um die lokale Zeitzone verschoben). DateTime-Vergleiche
|
||||
// berücksichtigen Kind nicht, sondern vergleichen nur rohe Ticks — ein direkter Vergleich
|
||||
// von local.Timestamp (Local, aus der Queue) mit remote.Timestamp (Utc, vom Server) wäre
|
||||
// daher außerhalb von UTC+0 falsch.
|
||||
_ => local.Timestamp.ToUniversalTime() >= remote.Timestamp.ToUniversalTime() ? local : remote,
|
||||
};
|
||||
|
||||
if (winner == remote) queue.Acknowledge([local.EventId]);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using LiteDB;
|
||||
|
||||
namespace LehrerApp.Sync.Models;
|
||||
|
||||
// ── Events ────────────────────────────────────────────────────────────────────
|
||||
@@ -5,6 +7,10 @@ namespace LehrerApp.Sync.Models;
|
||||
/// <summary>Desktop-Event: Payload ist AES-256-GCM verschlüsselt.</summary>
|
||||
public class SyncEvent
|
||||
{
|
||||
// LiteDB erkennt nur eine Property namens "Id" automatisch als Primärschlüssel.
|
||||
// Ohne [BsonId] würde ein eigener, von EventId unabhängiger _id vergeben, wodurch
|
||||
// EventQueue.Acknowledge()/_queue.Delete(EventId) niemals etwas löschen würde.
|
||||
[BsonId]
|
||||
public Guid EventId { get; init; } = Guid.NewGuid();
|
||||
public string DeviceId { get; init; } = "";
|
||||
public DeviceType DeviceType { get; init; }
|
||||
|
||||
Reference in New Issue
Block a user