From 3e504ca9c49492e157030a4295fd531a237a754f Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Mon, 10 Aug 2026 16:11:54 -0400 Subject: [PATCH] test(sessions): switch SessionWorkerClientFactoryFakeWorkerTests to IAsyncLifetime so its teardown actually runs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit xUnit v2 (2.9.3) never invokes IAsyncDisposable.DisposeAsync on a test class, so the unobserved-fault safety net this class documents — awaiting every scripted worker task after each test — has been dead code since it was written. Found via dumpasync on the wedged-testhost investigation: the NeverReadyWorkerProcessLauncher's Task.Delay(Infinite, _stop.Token) was still pending (DelayPromiseWithCancellation, detached) minutes after its test finished, which is only possible if DisposeAsync never ran. Proven both ways with a throw-probe in DisposeAsync: under IAsyncDisposable all 3 tests pass (never called); under IAsyncLifetime all 3 fail from the probe (called after every test). Sweep confirmed this is the only test class on IAsyncDisposable — all other implementers are helpers disposed via await using. --- .../SessionWorkerClientFactoryFakeWorkerTests.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionWorkerClientFactoryFakeWorkerTests.cs b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionWorkerClientFactoryFakeWorkerTests.cs index baeb902..c8f7047 100644 --- a/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionWorkerClientFactoryFakeWorkerTests.cs +++ b/src/ZB.MOM.WW.MxGateway.Tests/Gateway/Sessions/SessionWorkerClientFactoryFakeWorkerTests.cs @@ -11,7 +11,7 @@ using ZB.MOM.WW.MxGateway.Tests.TestSupport; namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Sessions; -public sealed class SessionWorkerClientFactoryFakeWorkerTests : IAsyncDisposable +public sealed class SessionWorkerClientFactoryFakeWorkerTests : IAsyncLifetime { private static readonly TimeSpan TestTimeout = TimeSpan.FromSeconds(5); @@ -24,12 +24,19 @@ public sealed class SessionWorkerClientFactoryFakeWorkerTests : IAsyncDisposable private readonly List _launchers = []; + /// + public Task InitializeAsync() => Task.CompletedTask; + /// /// Awaits every scripted worker task so an unhandled exception fails the owning test /// instead of surfacing later as an unobserved . + /// This must stay on : xUnit v2 never invokes + /// on a test class, so under the previous + /// declaration this teardown silently never ran (the NeverReady launcher's parked infinite + /// delay was still pending in a post-run process dump). /// /// A task that represents the asynchronous operation. - public async ValueTask DisposeAsync() + public async Task DisposeAsync() { foreach (IWorkerTaskLauncher launcher in _launchers) {