Conversation
- *Enhancement:* `TestSharedState` updated to enable request-based (isolated) state; with the corresponding `GetHttpRequestId()` method now made public.
- *Enhancement:* Added `ApiTesterBase.AddPreRunAction()`, `AddPostRunBeforeExpectationsAction()`, `AddPostRunAfterExpectationsAction()` and `AddPostRunAction()` to enable the addition of actions to be executed at different stages of the `Run`/`RunAsync` process for every underlying test. This will enable the addition of common pre/post processing logic without having to explicitly add to each test.
- *Enhancement:* `TEntryPoint` methods can now be specified as `static`.
- *Enhancement:* `ApiError` added implicit conversion from (`string?`, `string`) tuple to enable simplified usage; e.g. `AssertErrors(("field", "Bad Request"))` versus `AssertErrors(new ApiError("field", "Bad Request"))`.
- *Fixed:* Reset `MockHttpClientRequest` internal state when using any `With*` method to ensure correct behavior.
There was a problem hiding this comment.
Pull request overview
Release v5.10.0 introduces new extensibility hooks around the Run/RunAsync lifecycle, improves request-scoped shared state for HTTP testing, and includes several quality-of-life API changes and fixes (notably around MockHttpClient request reuse).
Changes:
- Add global pre/post run action hooks (with optional bypass) and wire them into relevant testers.
- Add request-id based shared state isolation and expose
GetHttpRequestId(). - Add
ApiErrorimplicit conversions and fix/reset behavior forMockHttpClientRequestreuse; plus assorted test/doc updates.
Reviewed changes
Copilot reviewed 30 out of 30 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/UnitTestEx.NUnit.Test/PersonControllerTest.cs | Updates tests to use new ApiError implicit conversions and updated mismatch formatting. |
| tests/UnitTestEx.NUnit.Test/Other/ObjectComparerTest.cs | Adds JSON path-ignore coverage for AssertJson. |
| tests/UnitTestEx.NUnit.Test/Other/GenericTest.cs | Updates entry-point test to validate static entry-point support. |
| tests/UnitTestEx.NUnit.Test/MockHttpClientTest.cs | Adds coverage to ensure request rules reset correctly across With* calls and “request not found” scenarios. |
| src/UnitTestEx/TesterArgs.cs | Introduces per-run args (e.g., bypassing configured run actions). |
| src/UnitTestEx/TestSetUp.cs | Fixes spelling in XML docs. |
| src/UnitTestEx/Resource.cs | Fixes spelling in XML docs (“qualified”). |
| src/UnitTestEx/ObjectComparer.cs | Fixes spelling in XML docs (“qualified”). |
| src/UnitTestEx/Mocking/MockHttpClientResponse.cs | Fixes param naming/spelling and XML docs (“milliseconds”, “qualified”). |
| src/UnitTestEx/Mocking/MockHttpClientRequestRule.cs | Adds rule reset helper to support request reuse. |
| src/UnitTestEx/Mocking/MockHttpClientRequest.cs | Resets internal state on With* methods to support safe reuse of request instances. |
| src/UnitTestEx/Mocking/MockHttpClient.cs | Fixes spelling in XML docs (“qualified”). |
| src/UnitTestEx/Hosting/ScopedTypeTester.cs | Wires run-action lifecycle (pre/post) into Run/RunAsync and adds optional TesterArgs. |
| src/UnitTestEx/Hosting/EntryPoint.cs | Extends reflection mapping to allow static entry-point methods. |
| src/UnitTestEx/Expectations/IExpectations.cs | Introduces marker interface to unify expectation-capable testers. |
| src/UnitTestEx/Expectations/ExpectationsExtensions.cs | Fixes spelling in XML docs (“qualified”). |
| src/UnitTestEx/Expectations/ExpectationsArranger.cs | Fixes spelling in XML docs (“originating”). |
| src/UnitTestEx/Assertors/ValueAssertor.cs | Fixes spelling in XML docs (“qualified”). |
| src/UnitTestEx/Assertors/HttpResponseMessageAssertorBaseT.cs | Fixes spelling in XML docs and summary (“Provides”, “qualified”). |
| src/UnitTestEx/Assertors/HttpResponseMessageAssertorBase.cs | Fixes spelling in XML docs summary (“Provides”). |
| src/UnitTestEx/Assertors/Assertor.cs | Improves error mismatch formatting and adds tuple-friendly output; fixes spelling (“Tries”). |
| src/UnitTestEx/Assertors/ActionResultAssertor.cs | Fixes spelling in XML docs (“qualified”). |
| src/UnitTestEx/AspNetCore/HttpTesterBase.cs | Integrates run-action lifecycle and request-scoped cleanup into HTTP send pipeline. |
| src/UnitTestEx/AspNetCore/ApiTesterBase.cs | Adds fluent APIs to register global pre/post run actions. |
| src/UnitTestEx/ApiError.cs | Adds implicit conversions from tuple and string for simplified assertions. |
| src/UnitTestEx/Abstractions/TesterBase.cs | Implements storage/execution of global pre/post run actions; fixes doc typos. |
| src/UnitTestEx/Abstractions/TestSharedState.cs | Exposes GetHttpRequestId() and adds request-scoped state dictionary helpers. |
| src/UnitTestEx.Azure.ServiceBus/ExtensionMethods.cs | Fixes spelling in XML docs (“qualified”). |
| Common.targets | Bumps package version to 5.10.0. |
| CHANGELOG.md | Adds v5.10.0 notes and corrects several typos in historical entries. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| finally | ||
| { | ||
| Owner.ExecutePreRunActions(this); | ||
| Owner.SharedState.RemoveRequestStateData(RequestId); | ||
| } |
There was a problem hiding this comment.
In the SendAsync overload that accepts object? value, the finally block calls Owner.ExecutePreRunActions(this) instead of executing post-run cleanup. This means post-run actions never run for this overload, and pre-run actions may run twice (once in try, once in finally). Replace this with Owner.ExecutePostRunActions(this) (consistent with the other overloads) and keep request-state cleanup here.
There was a problem hiding this comment.
@copilot apply changes based on this feedback
There was a problem hiding this comment.
@copilot apply changes based on this feedback
There was a problem hiding this comment.
Fixed in commit ea43b2c. The finally block now correctly calls Owner.ExecutePostRunActions(this) instead of Owner.ExecutePreRunActions(this).
| /// Resets the rule to the default values. | ||
| /// </summary> | ||
| /// <remarks>Does not reset the <see cref="Response"/> or <see cref="Times"/>.</remarks> | ||
| internal void Reset() | ||
| { | ||
| Body = null; | ||
| Response = null; | ||
| Responses = null; | ||
| ResponsesIndex = 0; |
There was a problem hiding this comment.
The Reset method documentation says it "Does not reset the Response", but the implementation sets Response = null. Either update the remarks to match the behavior (e.g., only mention Times is preserved), or change the implementation if Response truly should be retained.
| /// <summary> | ||
| /// Executes the post-run actions after the underlying test <b>Run</b> occurs (before <see cref="Expectations.ExpectationsArranger{TTester}.AssertAsync(Expectations.AssertArgs)"/>). | ||
| /// </summary> | ||
| /// <param name="tester">The <see cref="IExpectations"/> tester instance.</param> | ||
| internal void ExecutePostRunAfterExpectationsActions(IExpectations tester) | ||
| { |
There was a problem hiding this comment.
The XML doc for ExecutePostRunAfterExpectationsActions says the actions execute "before" ExpectationsArranger.AssertAsync, but the name (and call sites) indicate these run after expectations. Update the documentation to avoid misleading consumers.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Eric Sibly [chullybun] <eric@thesiblys.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Eric Sibly [chullybun] <eric@thesiblys.com>
…esterBase finally block Agent-Logs-Url: https://github.com/Avanade/UnitTestEx/sessions/aaa8d366-8973-4d7e-9cf4-e99050cedaf0 Co-authored-by: chullybun <12836934+chullybun@users.noreply.github.com>
HttpTesterBase.csfinallyblock incorrectly callingExecutePreRunActionsinstead ofExecutePostRunActions⌨️ Start Copilot coding agent tasks without leaving your editor — available in VS Code, Visual Studio, JetBrains IDEs and Eclipse.