dotnet-testing
.NET Testing Approach
This skill captures the approach, not a single library. The principles below apply regardless of which test runner, substitute library, or assertion library a project picks. Library routing is in §Library choices.
Floor: .NET 8 / C# 12. Testing classic ASP.NET on .NET Framework 4.8 (in-memory OWIN TestServer, HttpContextBase) is references/net-framework-48.md.
Test strategy by responsibility (architecture-neutral)
The strategy keys off the role a unit plays, not a layer name - so it maps onto whatever architecture the project picked. dotnet-web-backend owns the load-exactly-one-architecture rule but mandates no specific one. In a layered (Clean / Onion) project the roles below are the layers; in a vertical-slice / modular project they are the parts of a feature folder (the domain types, the handler / endpoint logic, the infrastructure wiring) - test each part the same way regardless of where it physically lives.
- Domain / business rules - pure unit tests, no substitutes. Cover entities, value objects, domain services, domain events, invariants, guard clauses, factory methods, and every branch of a business rule including exception paths. Target ~100%.
- Use cases / handlers / orchestration (the application logic of a slice or layer) - unit tests with all ports and abstractions substituted. Cover success paths, validation failures, exception handling, and orchestration branches. Target 95%+.
- Infrastructure / adapters - test logic-bearing code only (mappers, parsers, serializers, policy classes, retry/backoff, non-trivial query logic). Use in-memory DB or Testcontainers when query logic is non-trivial (
references/testcontainers.md). Do not write tests that only assert a substitute was configured. - Integration / E2E - defined per project in project CLAUDE.md. For an Aspire-orchestrated app the harness is
references/aspire-integration-testing.md. - Negative-security paths - assert the deny paths, not just the happy path: an expired or tampered token returns 401, N failed logins trip 429, and one user reading another's resource id returns 404. Explicit negative-security tests belong in the integration suite, not just the auth unit tests.