Test Minimal API 404 branches without booting a server
The author shows how to test the 404 branch of a minimal API endpoint by calling the handler directly instead of booting WebApplicationFactory. Typed result unions such as Results<Ok<T>, NotFound> make the return type a compiler-checked contract. The approach gives fast, readable unit tests, while the author keeps a thin layer of integration tests for routing, binding and middleware.
Key points
- Handlers returning IResult hide the status code from callers, so testing it normally requires executing the result through HTTP.
- Typed unions such as Results<Ok<Product>, NotFound> list the endpoint's possible outcomes directly in the method signature.
- TypedResults.Ok and TypedResults.NotFound return concrete Ok<T> and NotFound types that can be checked with pattern matching.
- The MapGet registration can keep pointing at the named handler method without any change to routing.
- Direct handler tests skip routing, model binding, serialization and middleware, so keep a thin set of integration tests for those.
- When a new response type is added to the union, the compiler flags the code and tests that need updating.
While adding a test for a missing product, the author noticed that booting a full web host just to check one if branch was wasteful. The root cause was that a handler returning IResult hides its status code, so the only way to learn it was to execute the result through HTTP. The fix is to move the handler into a named method that returns Results<Ok<Product>, NotFound>, which states the possible outcomes in the signature while leaving the route registration unchanged.
With that signature, the tests call the method directly and pattern-match the result to Ok<Product> or NotFound, finishing in about 15 milliseconds. The author is clear about the limits: these tests skip routing, model binding, serialization and middleware, so a small set of integration tests is still needed. The typed union also helps maintenance, since adding a new response type forces the compiler to flag the code and the tests that depend on it.
Real-world use
- A minimal API project where lookups of missing resources such as products return 404 and need a fast regression test.
- An xUnit suite that checks business branches in each endpoint handler without starting a host through WebApplicationFactory.
- An API team that wants the compiler to enforce the declared response types and keep OpenAPI metadata accurate.
Why it matters
Declaring typed union return types lets you test handler branches without a host and keeps the compiler aware of every possible response. Integration tests should still cover routing, binding and middleware.