A test suite is worth having when it tells you something you did not know. Most of the material below is about getting to that point: choosing a framework, faking the awkward dependency, and deciding which tests are worth the trouble of a real database.

The three frameworks come first, because that choice shapes every test you write afterwards and it is annoying to change. Then mocking, then the ASP.NET Core specifics, then the tests that run against real infrastructure.

Time, the file system, the clock and the network are what make a suite flaky. Each has an article here, and each is worth reading before you write the test, not after it starts failing on the build server.

Choosing a Test Framework

xUnit, NUnit and MSTest do the same job with different opinions about setup, parallelism and naming.

Mocking and Fakes

Replacing a dependency with something you control, and the point at which a mock is telling you the design is wrong.

Assertions and Test Data

Saying what you expected in a way that reads well when it fails, and producing the data to test it with.

Testing ASP.NET Core

Controllers, services and the whole application in memory.

The Awkward Dependencies: Time, Files and HTTP

Anything your test cannot control is a reason it will fail on somebody else’s machine. Here is the .NET answer to each.

Testcontainers and Real Infrastructure

Running the test against a real database in a container, which is often cheaper than the fake you were about to write.

UI and Browser Testing

Driving a real browser, with the usual warning about how much of your suite should work this way.

Performance and Load Testing

Asking how fast rather than whether it works.

Coverage and Practices

Measuring what the suite touches, and the practices around writing it.

Where to Go Next

What you are usually testing:

A test that has never failed has never been checked. Break the code on purpose once and watch it go red, then you know what it is actually asserting.