Pragmatic.Testing
Compile-time testing infrastructure for Pragmatic APIs: generated contract tests, a typed
test client (Api.*), and HTTP assertion helpers. Zero reflection — the source generator
reads the endpoint contracts your app already emits.
What you get
Section titled “What you get”| Piece | Where it lives | Purpose |
|---|---|---|
| Contract tests | generated into the test project | Authorization, CRUD and state-transition suites per endpoint — see Contract tests |
PragmaticTestIdentity | Pragmatic.Testing runtime | Dev-identity headers (AsUser) for acting as a specific user, tenant, or a caller with no permission at all |
Typed client Api.* | generated into the test project | Api.{Boundary}.{Name}Async(client, ...) → ApiResponse / ApiResponse<T>; routes and verbs resolved at compile time |
ApiResponse / ApiResponse<T> | Pragmatic.Testing runtime | Lazy deserialization (ReadAsync), chainable assertions, implicit conversion to HttpResponseMessage |
PragmaticHttpAssertions | Pragmatic.Testing runtime | ShouldBeOk(), ShouldBeCreated(), ShouldBeProblem(status) … framework-agnostic (BCL-only) |
PragmaticJson.Options | Pragmatic.Testing runtime | The host’s JSON conventions, for hand-rolled serialization in tests |
The client pairs with the ApiRoutes class the unified source generator emits into the app
assembly (route constants + typed URL builders) — rename a route and every test that calls
it breaks at build, not at runtime.
Quick Start
Section titled “Quick Start”The test project references the app plus both Testing pieces:
<ProjectReference Include="..\..\src\MyApp\MyApp.csproj" /><ProjectReference Include="...\Pragmatic.Testing\src\Pragmatic.Testing\Pragmatic.Testing.csproj" /><ProjectReference Include="...\Pragmatic.Testing.SourceGenerator\Pragmatic.Testing.SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />using Pragmatic.Testing; // ApiResponse, assertions, PragmaticJsonusing Pragmatic.Tests.Generated; // generated Api client
var created = await Api.Booking.CreateGuestAsync(Client, new{ firstName = "Ada", lastName = "Lovelace", email = "ada@example.com"});created.Raw.ShouldBeCreated();
var fetched = await Api.Guests.GetGuestAsync(Client, guestId);var dto = await fetched.ReadAsync(); // ApiResponse<GuestDto> → GuestDtoGenerated contract test classes join the PragmaticContractTests xUnit collection;
PragmaticContractTestBase exposes the shared Client wired once by the collection
fixture — no per-class setup.
| Getting started | Wiring the generator, the collection fixture, your first test |
| Contract tests | What each generated family asserts — and what it deliberately does not |
| Typed test client | The two tiers (ApiRoutes + Api), setup, usage, limits |
| Common mistakes | Denial tests that pass for the wrong reason, assertion strength, fixture wiring |
| Troubleshooting | Nothing generated, missing client, unexpected 401/400 |
License
Section titled “License”Part of the Pragmatic.Design ecosystem — see Licensing.