Skip to content

About

UnitTestEx provides .NET testing extensions to the most popular testing frameworks (MSTest, NUnit and Xunit) specifically to improve the testing experience with ASP.NET controller, and Azure Function, execution including underlying HttpClientFactory mocking.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

28 stars

Watchers

3 watching

Forks

Repository files navigation


Logo


Introduction

UnitTestEx provides .NET testing extensions for MSTest, NUnit and xUnit. It hosts your real application (API, Azure Function, or any DI-composed code) inside the test, lets you replace or mock its dependencies, and gives you fluent Arrange, Act, Assert testing with captured logging and detailed JSON-diff assertions.

v6 targets .NET 8, 9 and 10, and the Azure Functions v4 isolated worker model only. Upgrading? See Migrating from v5 to v6.


Status

CI UnitTestEx UnitTestEx.Azure.Functions UnitTestEx.Aspire UnitTestEx.MSTest UnitTestEx.NUnit UnitTestEx.Xunit
CI NuGet version NuGet version NuGet version NuGet version NuGet version NuGet version

The change log details all key changes per published version.


Which tester?

Testing... Use Package(s) Hosts Docs
An ASP.NET Core API (controllers or minimal APIs) ApiTester UnitTestEx + framework package WebApplicationFactory, full HTTP pipeline API testing
An Azure Function (isolated worker) FunctionTester UnitTestEx.Azure.Functions Your real Program.cs host, built but not started; the function is invoked directly Azure Functions
Any DI-composed class or service GenericTester UnitTestEx Lightweight Generic Host Generic testing
Multiple real services together AspireTester UnitTestEx.Aspire .NET Aspire DistributedApplication Aspire

The framework package (UnitTestEx.NUnit, UnitTestEx.MSTest or UnitTestEx.Xunit) wires output and assertions into your test framework.

Functions proof boundary: FunctionTester proves invocation behavior, not trigger indexing, binding conversion, broker delivery or final runtime HTTP behavior. Use Aspire/Core Tools with the backing service or emulator for those checks. Posting a BlobCreated webhook simulates notification delivery; it does not test Azure Event Grid. Start with the Functions guide and runnable Blob example.


Quick start

API: send a real HTTP request through the pipeline, with a downstream HttpClient mocked.

var mcf = MockHttpClientFactory.Create();
mcf.CreateClient("XXX", new Uri("https://somesys"))
    .Request(HttpMethod.Get, "products/abc").Respond.WithJson(new { id = "Abc", description = "A blue carrot" });

using var test = ApiTester.Create<Startup>();
test.ReplaceHttpClientFactory(mcf)
    .Controller<ProductController>()
    .Run(c => c.Get("abc"))
    .AssertOK()
    .AssertValue(new { id = "Abc", description = "A blue carrot" });

Azure Function: Program.cs runs as-is, with no test-only structure needed.

using var test = FunctionTester.Create<ProductFunction>();
test.ReplaceHttpClientFactory(mcf)
    .HttpTrigger<ProductFunction>()
    .Run(f => f.Run(test.CreateHttpRequest(HttpMethod.Get, "product/abc"), "abc"))
    .AssertOK()
    .AssertValue(new { id = "Abc", description = "A blue carrot" });

test.ServiceBusTrigger<ServiceBusFunction>()
    .Run(f => f.Run2(test.CreateServiceBusMessageFromValue(new Person { FirstName = "Bob", LastName = "Smith" })))
    .AssertSuccess();

Generic: any service, with expectations declared up front.

using var test = GenericTester.Create<EntryPoint>();
test.ExpectException().Type<DivideByZeroException>()
    .Run<Gin>(gin => gin.Stir());

Capabilities

Each row links to the docs and to a test that shows it working.

Capability Applies to Example
Controller tests from a method expression; route, method and body are inferred API Get_Test1
Raw HTTP requests, typed responses API Http_Update_Http2
ValidationProblemDetails / error assertions API, Function ValidationProblemDetails
HTTP trigger: HttpRequest → IActionResult / IResult Function HttpTrigger_ActionResult_Sync, HttpTrigger_Result_Async
HTTP trigger: HttpRequestData → HttpResponseData Function HttpTrigger_RequestData_Json
HTTP method/route validated against [HttpTrigger] Function HttpTrigger_RequestData_RouteCheck, WithPathAndQueryCheck
Multi-output bindings Function HttpTrigger_MultiOutput
Service Bus trigger and message settlement Function ServiceBusMessage_Success, ServiceBusMessage_AssertActions
Event Grid (EventGridEvent / CloudEvent) builders Function EventGridEvent_FromValue, CloudEvent_FromJson
Worker middleware pipeline (logging, short-circuit, exception mapping) Function Middleware_ShortCircuit_ActionResult, Middleware_HandlesException_HttpResponseData
Other triggers (Timer, Blob, Queue, ...) Function TimerTriggered, BlobTrigger_Bytes, QueueTrigger_Person, GenericTrigger_ServiceBus
Real Program.cs with test overrides; worker never started Function Program_TestOverrides, Program_ServicesUsed_WorkerNotStarted
Run any service, sync or async Generic Run_Service
Scoped services (ScopedType<T>) All ScopedType_RunsWithinServiceScope
Replace / mock DI registrations All ReplaceSingleton_OverridesRegistration, MockSingleton_UsesMoqObject
Configuration overrides, appsettings.unittest.json All Configuration_Overrride_Use
HttpClient mocking: match, sequence, delay, times, YAML All MockSequence, WithYamlRequests
Expect* before or Assert* after All Update_Test5_ExpectationFailure, ExpectValue_WithFunc
JSON-diff comparison with paths to ignore All PathsToIgnore_PropertyName
Log capture and log assertions All Get_Test1_ExpectLogNotContains_Failure, Checkpoint_WritesReasonAndFlushesLogsToOutput
One-off assembly set-up and tester extensions All TesterExtensions_FunctionTester
Multi-host tests with WireMock stubs and log checks Aspire HttpMock_StubsExternalMockHostDependency_Product, ErrorWhenLogContains_DefaultsToEnabled_ThrowsWithoutExplicitRegistration

Documentation


Examples

The tests in this repository are the reference examples. Equivalent tests exist for each framework, with only framework-specific differences:


Other repos

These other Avanade repositories leverage UnitTestEx to provide unit testing capabilities:

  • CoreEx - Enriched capabilities for building business services by extending the core capabilities of .NET.
  • Beef - Business Entity Execution Framework to enable industralisation of API development.

License

UnitTestEx is open source under the MIT license and is free for commercial use.


Contributing

One of the easiest ways to contribute is to participate in discussions on GitHub issues. You can also contribute by submitting pull requests (PR) with code changes. Contributions are welcome. See information on contributing, as well as our code of conduct.


Security

See our security disclosure policy.


Who is Avanade?

Avanade is the leading provider of innovative digital and cloud services, business solutions and design-led experiences on the Microsoft ecosystem, and the power behind the Accenture Microsoft Business Group.

About

UnitTestEx provides .NET testing extensions to the most popular testing frameworks (MSTest, NUnit and Xunit) specifically to improve the testing experience with ASP.NET controller, and Azure Function, execution including underlying HttpClientFactory mocking.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

28 stars

Watchers

3 watching

Forks

Releases

Used by

Contributors

Languages