Skip to content

Reset test-double state after each test through a test-only IResettableTestState contract, so the test harness clears its captures and stubs on its own, and bound every resource reset by the step timeout - #435

Open
Vulthil wants to merge 1 commit into
mainfrom
reset-test-state-between-tests
Open

Vulthil wants to merge 1 commit into
mainfrom
reset-test-state-between-tests

Conversation

@Vulthil

@Vulthil Vulthil commented Oct 2, 2026

Copy link
Copy Markdown
Owner

Summary

Test-double state in a test host is now reset after each test, through a test-only contract, and every resource reset has the same time limit as the other reset steps.

Before, the messaging test harness kept its captured messages and its Handle/Respond stubs for the whole life of the host. A test class that shared one host saw the earlier tests' messages, and a stub from one test kept answering in the next tests. The testing article told users to call Clear() from Initialize(), but resolving the harness there builds the host before the test can register its doubles, so GetMock/Use then throw. Clear() also kept the stubs. Separately, the article said that every reset step has a 30-second bound, but only the service stop and restart steps had one: a resource reset that hung blocked the teardown forever.

  • IResettableTestState (new, in Vulthil.Extensions.Testing, the framework-agnostic test package): state that a test double keeps in a test host's services, with ValueTask ResetAsync(CancellationToken). It lives in a test package, so no runtime package gets a test-only seam.
  • Test harness: UseTestHarness() / ReplaceTransportWithTestHarness() also register the harness as an IResettableTestState. Its reset clears the captured messages and removes the stubs. Clear() keeps its meaning (captured messages only). ITestHarness is unchanged.
  • Vulthil.xUnit: after each test, BaseIntegrationTestCase resets every IResettableTestState of every live host of the class, in the same pause as the database reset. Every live host, not only the newest, because the next test can run on the class's shared host after a test that ran on a per-test host. An instance that two hosts share is reset once.
  • Step bound: resource resets and test-state resets now run on the same 30-second step bound as the stop and restart steps (the token is cancelled, and a reset that ignores it is abandoned), so the code matches the documented contract. One step runner now serves every step.
  • Docs: testing.md drops the Initialize()/Clear() advice, documents the automatic reset and when startup messages are visible, and gets a "Resetting your own test doubles" section; the package pages, the harness README and the XML docs are updated.

Public API: one added interface (Vulthil.Extensions.Testing.IResettableTestState). Vulthil.xUnit and Vulthil.Messaging.TestHarness now depend on Vulthil.Extensions.Testing. No break.

Verification

  • dotnet build Vulthil.SharedKernel.slnx: 0 warnings, 0 errors.
  • All 18 unit test projects pass on net10.0 and net9.0. New tests:
    • 5 in TestHarnessTests: the harness is the host's only resettable test state; a reset clears the captured messages; a reset removes the Handle stubs; a reset removes the Respond stubs so the request consumer answers again; Clear() keeps the stubs.
    • 4 in TestHostResetTests: test states reset while the services are stopped; a failing test-state reset is reported and the services still restart; a resource reset that never completes is abandoned at the step bound and the services restart; a test-state reset that honours its token is cancelled at the step bound.
    • 3 in TestHostScopeTests: the test states of every live host are reset; a state that two live hosts share is reset once; the states of a stopped host are not reset.
    • 1 in Vulthil.IntegrationTests (TestHarnessResetIntegrationTests, Docker): the teardown after a test clears the shared host's harness captures and stubs.
  • Vulthil.IntegrationTests (Docker): 71/71 on net10.0 and net9.0.
  • Aspire MessagingIntegrationTests: 13/13 on net10.0.
  • dotnet pack package validation against 1.2.0 passes for Vulthil.Extensions.Testing, Vulthil.Messaging.TestHarness and Vulthil.xUnit.
  • docfx docs build: 0 warnings, 0 errors.
  • Break checks (each made tests fail, then reverted):
    • the reset keeps the stubs: 2 harness tests and the Docker test fail;
    • Clear() also removes the stubs: 1 harness test fails;
    • the harness is not registered as a test state: 4 harness tests and the Docker test fail;
    • only the newest host's states are reset: 1 scope test fails;
    • a state shared by two hosts is not deduplicated: 1 scope test fails;
    • the reset ignores the test states: 6 tests fail;
    • the token is not passed to the test state: 1 test fails;
    • resource resets without the step bound: the never-completing resource test hangs, which is the old behaviour.

Backport to v1.0: no

…leTestState contract, so the test harness clears its captures and stubs on its own, and bound every resource reset by the step timeout

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant