Repository navigation
Conversation
- Target net8.0/net9.0/net10.0 only; remove net6/net7 conditional code. - Remove UnitTestEx.Azure.ServiceBus; move ServiceBus helpers into UnitTestEx.Azure.Functions (no reflection). - FunctionTester builds the isolated worker host by executing the app's own entry point (top-level Program.cs as-is), capturing the host at Build() and never starting the worker. - Relax FunctionTester TEntryPoint new() constraint; any app type can be the marker. - Isolated sample uses template-style Program.cs and Worker 2.x; add isolated tests. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- Remove in-process/WebJobs support, legacy FunctionsStartup fallback and WebJobs Service Bus assertors - Add generic TriggerTester (instance and static methods) and FunctionOutputAssertor for multi-output functions - Support HttpRequest/IActionResult/IResult and HttpRequestData/HttpResponseData with HttpResponseMessage assertion - Migrate in-process test fixture to UnitTestEx.IsolatedFunction; update NUnit/xUnit/MSTest tests - Update README for isolated-worker model Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add worker middleware testing, Event Grid helpers, HTTP no-body matching, and expand documentation and coverage. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Expand isolated Functions trigger helpers, add Service Bus emulator integration coverage, update docs, and run CI tests sequentially across .NET 8/9/10. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical defects allow tests to hang despite timeouts, lose middleware changes through duplicate argument evaluation, and prevent the Service Bus Functions host from starting on a clean checkout.
6 open issues
Bound timeout must await the action task · New Invoke with evaluated middleware arguments · New Add and copy host.json for Functions project · New Preserve EventGridEvent topic in webhook payload · New Mark optional MVC name parameters nullable · New Provision broker connections for all indexed triggers · New
What changed in this PR
This PR expands Azure Functions and Aspire testing support, adds Event Hubs builders and Service Bus emulator coverage, and migrates to isolated-worker Functions on .NET 8–10.
Changes:
- Add host capture, middleware-aware invocation, event builders, and HTTP/multi-output assertions.
- Add Aspire emulator fixtures, shared lifecycle support, asynchronous polling, and consistent no-body HTTP mocking.
- Migrate cross-framework tests, document v6 changes, and run CI test projects sequentially.
This pull request requires changes. Three critical and four moderate findings remain unresolved, covering invocation correctness, timeout enforcement, event metadata, optional query parameters, and integration-host startup.
| File | Description |
|---|---|
tests/UnitTestEx.Xunit.Test/UnitTestEx.Xunit.Test.csproj |
Reference isolated-worker fixtures and HTTP compatibility helpers. |
tests/UnitTestEx.Xunit.Test/ServiceBusFunctionTest.cs |
Migrate Service Bus tests to isolated workers. |
tests/UnitTestEx.Xunit.Test/Resources/HttpMockInterfaceTest-mock.unittestex.yaml |
Add an omitted-body stub. |
tests/UnitTestEx.Xunit.Test/ProductFunctionTest.cs |
Migrate product function tests. |
tests/UnitTestEx.Xunit.Test/PersonFunctionTest.cs |
Migrate person function tests and request construction. |
tests/UnitTestEx.Xunit.Test/MockHttpClientTest.cs |
Import HTTP JSON extensions. |
tests/UnitTestEx.Xunit.Test/HttpMockInterfaceTest.cs |
Test absent and empty request-body matching. |
tests/UnitTestEx.NUnit.Test/UnitTestEx.NUnit.Test.csproj |
Remove legacy fixture references and add compatibility helpers. |
tests/UnitTestEx.NUnit.Test/StorageTriggerTest.cs |
Add blob and queue invocation tests. |
tests/UnitTestEx.NUnit.Test/ServiceBusFunctionTest.cs |
Migrate invocation and settlement assertions. |
tests/UnitTestEx.NUnit.Test/ProductFunctionTest.cs |
Migrate HTTP and timer tests. |
tests/UnitTestEx.NUnit.Test/Other/OneOffTestSetUpTest.cs |
Use an isolated-worker fixture. |
tests/UnitTestEx.NUnit.Test/Other/ExpectationsTest.cs |
Document the synchronous assertion helper. |
tests/UnitTestEx.NUnit.Test/Other/EventuallyAsyncTest.cs |
Test polling, timeout, and cancellation behavior. |
tests/UnitTestEx.NUnit.Test/Other/DocumentationLinksTest.cs |
Validate relative documentation links. |
tests/UnitTestEx.NUnit.Test/Other/DependencyInjectionTest.cs |
Cover service replacement, mocking, and scoped resolution. |
tests/UnitTestEx.NUnit.Test/MockHttpClientTest.cs |
Import HTTP JSON extensions. |
tests/UnitTestEx.NUnit.Test/EventHubsTest.cs |
Cover Event Hubs builders and trigger invocation. |
tests/UnitTestEx.NUnit.Test/EventGridExtensionMethodsTest.cs |
Cover Event Grid and CloudEvent builders. |
tests/UnitTestEx.MSTest.Test/UnitTestEx.MSTest.Test.csproj |
Reference isolated-worker fixtures and compatibility helpers. |
tests/UnitTestEx.MSTest.Test/ServiceBusFunctionTest.cs |
Migrate Service Bus tests. |
tests/UnitTestEx.MSTest.Test/ProductFunctionTest.cs |
Migrate product function tests. |
tests/UnitTestEx.MSTest.Test/PersonFunctionTest.cs |
Migrate person function tests. |
tests/UnitTestEx.MSTest.Test/Other/JsonElementComparerTest.cs |
Make expected difference separators explicit. |
tests/UnitTestEx.MSTest.Test/MockHttpClientTest.cs |
Import HTTP JSON extensions. |
tests/UnitTestEx.IsolatedFunction/UnitTestEx.IsolatedFunction.csproj |
Target .NET 8–10 and update worker extensions. |
tests/UnitTestEx.IsolatedFunction/TestMiddleware.cs |
Add logging, denial, and exception-handling fixtures. |
tests/UnitTestEx.IsolatedFunction/StorageTriggerFunctions.cs |
Add blob and queue function fixtures. |
tests/UnitTestEx.IsolatedFunction/Startup.cs |
Remove the custom startup bridge. |
tests/UnitTestEx.IsolatedFunction/ServiceBusFunction.cs |
Expand isolated-worker Service Bus scenarios. |
tests/UnitTestEx.IsolatedFunction/Program.cs |
Configure services and middleware through normal startup. |
tests/UnitTestEx.IsolatedFunction/ProductFunction.cs |
Add isolated-worker HTTP and timer fixtures. |
tests/UnitTestEx.IsolatedFunction/PersonFunction.cs |
Add isolated-worker person endpoints. |
tests/UnitTestEx.IsolatedFunction/HttpVariantFunctions.cs |
Add HTTP response-model and multi-output fixtures. |
tests/UnitTestEx.IsolatedFunction/EventHubsFunctions.cs |
Add single-event, batch, and failure fixtures. |
tests/UnitTestEx.Function/UnitTestEx.Function.csproj |
Remove the in-process sample project. |
tests/UnitTestEx.Function/Startup.cs |
Remove WebJobs startup configuration. |
tests/UnitTestEx.Function/ServiceBusFunction.cs |
Remove in-process Service Bus fixtures. |
tests/UnitTestEx.Function/Properties/serviceDependencies.local.json |
Remove legacy local dependency metadata. |
tests/UnitTestEx.Function/Properties/serviceDependencies.json |
Remove legacy dependency metadata. |
tests/UnitTestEx.Function/ProductFunction.cs |
Remove in-process product fixtures. |
tests/UnitTestEx.Function/PersonFunction.cs |
Remove in-process person fixtures. |
tests/UnitTestEx.Function/host.json |
Remove the legacy sample’s host configuration. |
tests/UnitTestEx.Function/.gitignore |
Remove the legacy project’s ignore rules. |
tests/UnitTestEx.Aspire.Xunit.Test/Resources/AspireTesterTest-mock.unittestex.yaml |
Add an omitted-body Aspire stub. |
tests/UnitTestEx.Aspire.Xunit.Test/AspireTesterTest.cs |
Test Aspire no-body matching. |
tests/UnitTestEx.Aspire.ServiceBus.Function/UnitTestEx.Aspire.ServiceBus.Function.csproj |
Add a dedicated Service Bus function project. critical — 3 votes, line 14: Add a minimal version-2 host.json and copy it to output; Core Tools otherwise cannot locate the app root. |
tests/UnitTestEx.Aspire.ServiceBus.Function/ServiceBusEchoFunction.cs |
Echo triggered messages to an output queue. |
tests/UnitTestEx.Aspire.ServiceBus.Function/Program.cs |
Add standard worker startup. |
tests/UnitTestEx.Aspire.ServiceBus.AppHost/UnitTestEx.Aspire.ServiceBus.AppHost.csproj |
Add the Service Bus integration AppHost. |
tests/UnitTestEx.Aspire.ServiceBus.AppHost/ServiceBus/Config.json |
Define emulator input and output queues. |
tests/UnitTestEx.Aspire.ServiceBus.AppHost/AppHost.cs |
Orchestrate SQL, Service Bus, and Core Tools. moderate — 1 vote, line 36: Manage Azurite with a startup dependency or provide working storage; UseDevelopmentStorage=true currently relies on an external local process. |
tests/UnitTestEx.Aspire.NUnit.Test/UnitTestEx.Aspire.NUnit.Test.csproj |
Reference storage clients and integration AppHosts. |
tests/UnitTestEx.Aspire.NUnit.Test/Functions/ServiceBusEmulatorTest.cs |
Exercise broker-triggered processing and output. |
tests/UnitTestEx.Aspire.NUnit.Test/Functions/AzuriteBlobTriggerTest.cs |
Exercise blob webhook processing and output. |
tests/UnitTestEx.Aspire.NUnit.Test/AspireTesterTest.cs |
Share an AppHost and test lifecycle hooks. |
tests/UnitTestEx.Aspire.Functions.AppHost/UnitTestEx.Aspire.Functions.AppHost.csproj |
Add the storage integration AppHost. |
tests/UnitTestEx.Aspire.Functions.AppHost/AppHost.cs |
Launch Azurite and the Functions host. moderate — 2 votes, line 23: Restrict the fixture to the blob function and update expectations, or provision Service Bus/Event Hubs connections to avoid unrelated trigger errors. |
tests/UnitTestEx.Api/Controllers/PersonController.cs |
Update query-parameter nullability. moderate — 3 votes, line 46: Mark both name parameters nullable; [ApiController] otherwise returns HTTP 400 when they are omitted, breaking GetByArgs_Test2. |
src/UnitTestEx/UnitTestEx.csproj |
Drop older frameworks and expose internals to Functions. |
src/UnitTestEx/Schema/mock.unittestex.json |
Describe omitted-body matching semantics. |
src/UnitTestEx/Resource.cs |
Document YAML scalar resolution. |
src/UnitTestEx/ObjectComparer.cs |
Remove legacy framework branches. |
src/UnitTestEx/Mocking/MockHttpClientResponse.cs |
Simplify JSON syntax annotations. |
src/UnitTestEx/Mocking/MockHttpClientRequest.cs |
Add explicit no-body and empty-content matching. |
src/UnitTestEx/Mocking/MockHttpClient.cs |
Simplify URI syntax annotations. |
src/UnitTestEx/Mocking/IHttpMockRequest.cs |
Expose the shared no-body contract. |
src/UnitTestEx/Mocking/HttpMockResourceConfig.cs |
Apply no-body semantics to omitted resource bodies. |
src/UnitTestEx/Logging/LoggerBase.cs |
Remove obsolete scope-signature branching. |
src/UnitTestEx/Json/JsonElementComparer.cs |
Simplify JSON syntax annotations. |
src/UnitTestEx/Hosting/HostTesterBase.cs |
Add synchronous/static execution and pipeline interception. critical — 3 votes, line 190: Invoke with already evaluated arguments; reevaluating the expression gives middleware and the function different request/context instances, losing middleware changes. |
src/UnitTestEx/Hosting/EntryPoint.cs |
Make modern host configuration unconditional. |
src/UnitTestEx/Generic/GenericTesterCore.cs |
Remove the legacy host-building path. |
src/UnitTestEx/Expectations/ExpectationsExtensions.cs |
Simplify JSON expectation declarations. |
src/UnitTestEx/Assertors/ValueAssertor.cs |
Remove legacy JSON and HTTP-result branches. |
src/UnitTestEx/Assertors/HttpResultAssertor.cs |
Make HTTP-result assertions unconditional. |
src/UnitTestEx/Assertors/HttpResponseMessageAssertorBaseT.cs |
Simplify JSON assertion declarations. |
src/UnitTestEx/Assertors/ActionResultAssertor.cs |
Simplify JSON assertion declarations. |
src/UnitTestEx/AspNetCore/HttpTesterT.cs |
Remove legacy URI annotation branches. |
src/UnitTestEx/AspNetCore/HttpTesterBase.cs |
Simplify HTTP request method declarations. |
src/UnitTestEx/AspNetCore/HttpTester.cs |
Simplify public HTTP tester declarations. |
src/UnitTestEx/Abstractions/TesterBaseCore.cs |
Add asynchronous polling. critical — 3 votes, line 177: Bound the returned-task wait with operationToken, retaining timeout-to-TimeoutException conversion; token-ignoring actions can otherwise hang despite timeout or caller cancellation. |
src/UnitTestEx.Xunit/UnitTestEx.Xunit.csproj |
Target .NET 8–10 only. |
src/UnitTestEx.NUnit/UnitTestEx.NUnit.csproj |
Target .NET 8–10 only. |
src/UnitTestEx.MSTest/UnitTestEx.MSTest.csproj |
Target .NET 8–10 only. |
src/UnitTestEx.Azure.ServiceBus/UnitTestEx.Azure.ServiceBus.csproj |
Remove the standalone Service Bus package project. |
src/UnitTestEx.Azure.Functions/UnitTestEx.Azure.Functions.csproj |
Drop WebJobs dependencies and add event SDKs. |
src/UnitTestEx.Azure.Functions/ServiceBusExtensionMethods.cs |
Provide relocated Service Bus message builders. |
src/UnitTestEx.Azure.Functions/FunctionTester.cs |
Accept any application-assembly marker type. |
src/UnitTestEx.Azure.Functions/EventHubsExtensionMethods.cs |
Add received Event Hubs event builders. |
src/UnitTestEx.Azure.Functions/EventGridExtensionMethods.cs |
Add Event Grid, CloudEvent, and blob-event builders. |
src/UnitTestEx.Azure.Functions/Azure/Functions/WorkerServiceBusMessageActionsAssertor.cs |
Correct worker-specific documentation references. |
src/UnitTestEx.Azure.Functions/Azure/Functions/TestHttpResponseData.cs |
Add worker response and cookie implementations. |
src/UnitTestEx.Azure.Functions/Azure/Functions/TestHttpRequestData.cs |
Wrap ASP.NET Core requests for worker tests. |
src/UnitTestEx.Azure.Functions/Azure/Functions/TestFunctionContext.cs |
Add a configurable worker invocation context. |
src/UnitTestEx.Azure.Functions/Azure/Functions/ServiceBusMessageActionStatus.cs |
Reference worker settlement APIs in documentation. |
src/UnitTestEx.Azure.Functions/Azure/Functions/HttpResponseDataAssertor.cs |
Convert worker responses for HTTP assertions. |
src/UnitTestEx.Azure.Functions/Azure/Functions/FunctionTesterT.cs |
Remove the parameterless-constructor requirement. |
src/UnitTestEx.Azure.Functions/Azure/Functions/FunctionOutputAssertor.cs |
Add multi-output property and HTTP assertions. |
src/UnitTestEx.Azure.Functions/Azure/Functions/FunctionHostFactory.cs |
Capture application hosts without starting workers. |
src/UnitTestEx.Aspire/WithAspireTester.cs |
Add shared-fixture lifecycle and disposal support. |
src/UnitTestEx.Aspire/UnitTestEx.Aspire.csproj |
Add Event Grid and MessagePack dependencies. |
src/UnitTestEx.Aspire/Aspire/HttpMock/AspireHttpMockRequest.cs |
Implement Aspire no-body matching. |
src/UnitTestEx.Aspire/Aspire/FunctionsWebhookClient.cs |
Post Event Grid notifications to runtime webhooks. moderate — 2 votes, line 100: Preserve the supplied Topic; use the placeholder only when absent so topic-dependent functions receive faithful metadata. |
docs/test-setup-and-extensibility.md |
Explain setup, framework support, and extension hooks. |
docs/migration-v6.md |
Document breaking changes and migration steps. |
docs/generic-testing.md |
Explain generic and scoped testing. |
docs/dependency-injection-and-configuration.md |
Explain overrides, configuration, and host lifetime. |
docs/assertions-and-expectations.md |
Explain assertions, comparisons, and logging. |
docs/api-testing.md |
Explain controller and HTTP testing. |
CHANGELOG.md |
Record v6 changes and update documentation links. |
.github/workflows/ci.yml |
Install Core Tools and test .NET 8–10 sequentially. |
Review effort: Balanced
Document Event Hubs and Service Bus additions in the v6.0.0 changelog. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: Eric Sibly <eric.sibly@avanade.com>
Bound eventual-operation waits, reuse evaluated invocation arguments, preserve Event Grid topics, and make the blob and Service Bus emulator fixtures self-contained. Add regression coverage and update Aspire documentation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: Eric Sibly <eric.sibly@avanade.com>
Remove the redundant target framework override from the single-target Functions project reference so MSBuild reuses the solution build instance instead of concurrently writing the same outputs. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: Eric Sibly <eric.sibly@avanade.com>
- Set package version to 6.0.0 and update NuGet publishing. - Improve Aspire and Azure Functions host lifecycle, scope cleanup, and error handling. - Define HTTP mock body matching for empty and non-empty requests. - Make `ValueAssertor.AssertJson` compare JSON structurally. - Update documentation and add regression tests.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Overview
This is the UnitTestEx v6.0.0 major release. It moves the supported baseline to .NET 8, 9 and 10 and aligns Azure Functions testing with the v4 isolated worker model, removing the legacy in-process path and out-of-support .NET targets. The goal is to keep UnitTestEx aligned with the supported Azure Functions/.NET ecosystem while preserving its low-friction testing model, including real application startup, trigger and middleware execution, assertions, and captured logging.
v6.0.0 changes
net8.0,net9.0andnet10.0only;net6.0andnet7.0(both out of support) have been removed.UnitTestEx.Azure.Functionssupports the Azure Functions v4 isolated worker model only; in-process (WebJobs) support has been removed, including theFunctionsStartupentry point andCreateWebJobsServiceBus*MessageActions. See Migrating from v5 to v6.UnitTestEx.Azure.ServiceBushas been removed; itsCreateServiceBusMessage*helpers now live inUnitTestEx.Azure.Functions(sameUnitTestExnamespace).FunctionTesterruns the function app's realProgram.cs(top-level statements supported; no test-specific structure required), capturing the host atBuild()without starting the worker; test configuration and service overrides are applied.TEntryPointis any type within the function app assembly.HttpTrigger<T>supports both ASP.NET Core integration (HttpRequest→IActionResult/IResult) and built-in (HttpRequestData→HttpResponseData) HTTP models, asserted consistently viaHttpResponseMessageAssertor; method and route are validated against the workerHttpTriggerAttribute.Trigger<T>enables any other trigger type to be tested, withFunctionOutputAssertorfor multi-output bindings.CreateEventGridEvent*andCreateCloudEvent*.EventDatabuilders for values, JSON, resources and raw bodies, with broker metadata support.FunctionTesternow runs the function app's worker middleware pipeline (including the ASP.NET Core integration) around the invoked method, so middleware logging, short-circuiting and exception mapping can be asserted. UseUseWorkerMiddleware(false)to invoke the method directly.IHttpMockRequest.WithNoBody()(implemented byMockHttpClientRequestandAspireHttpMockRequest), which matches a request with no body: absent or zero-length. The two are indistinguishable on the wire, so both tiers treat them identically. As a result:Content == nullmatched.IHttpMockClient.WithRequestsFromResourceAsyncloader now treats an omittedbodyasWithNoBody(), consistent with Tier 1's native loader. Previously it matched any body, so Aspire stubs that omitbodyno longer match requests that have one; usebody: ^for that. On Aspire,GET/HEAD(or an unspecified method) apply no body constraint, as WireMock.Net does not read those bodies by default.docs/.