diff --git a/tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/Integration/AuditWriteFailureSafetyTests.cs b/tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/Integration/AuditWriteFailureSafetyTests.cs index 34c94dd9..48214a9b 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/Integration/AuditWriteFailureSafetyTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/Integration/AuditWriteFailureSafetyTests.cs @@ -330,8 +330,22 @@ public class AuditWriteFailureSafetyTests : TestKit, IClassFixture= 1, - $"Expected dispatcher to attempt audit write at least once; saw {throwingWriter.Attempts}."); + // AwaitAssert, not a bare Assert: the dispatcher persists the delivery + // state BEFORE emitting the audit rows (DeliverOneAsync updates the + // row, then emits Attempted, then the terminal), so seeing Delivered + // above orders nothing with respect to the audit write — on a loaded + // parallel run the post-write continuation can land after the poll that + // observed Delivered, producing a spurious "saw 0". The bounded wait + // keeps the assertion's force: the writer must actually be invoked + // within the timeout or the test fails exactly as before. + await AwaitAssertAsync( + () => + { + Assert.True(throwingWriter.Attempts >= 1, + $"Expected dispatcher to attempt audit write at least once; saw {throwingWriter.Attempts}."); + return Task.CompletedTask; + }, + TimeSpan.FromSeconds(15)); } // --------------------------------------------------------------------- diff --git a/tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/Integration/NotifyDispatcherAuditTrailTests.cs b/tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/Integration/NotifyDispatcherAuditTrailTests.cs index 9135011d..7e498def 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/Integration/NotifyDispatcherAuditTrailTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/Integration/NotifyDispatcherAuditTrailTests.cs @@ -324,8 +324,24 @@ public class NotifyDispatcherAuditTrailTests : TestKit, IClassFixture= 2, - $"Expected the dispatcher to attempt audit writes; saw {throwingWriter.AttemptCount}"); + // + // AwaitAssert, not a bare Assert: the dispatcher deliberately persists + // the delivery state BEFORE emitting either audit row (DeliverOneAsync + // writes the row, then Attempted, then the terminal), so observing + // Delivered above establishes NO happens-before edge with the audit + // writes — under a loaded parallel run the continuation after the DB + // write can be scheduled after the poll that saw Delivered, yielding a + // spurious "saw 0". The bounded wait removes the ordering assumption + // without weakening the claim: the writer must genuinely be invoked at + // least twice inside the timeout or the test still fails. + await AwaitAssertAsync( + () => + { + Assert.True(throwingWriter.AttemptCount >= 2, + $"Expected the dispatcher to attempt audit writes; saw {throwingWriter.AttemptCount}"); + return Task.CompletedTask; + }, + TimeSpan.FromSeconds(15)); } ///