← Back to articles

FastAPI · Testing

FastAPI Endpoint Tests: Assert the Contract, Not Just a Green Status

Test response bodies and rejection paths alongside status codes to make API contracts observable.

A blue API testing bench inspects structured response tiles and separates successful requests from rejected inputs.
Inspect both the response status and the contract carried by its body.

An endpoint test should explain the promise made to its caller. A green response alone cannot show that the API returned the right fields or rejected invalid input.

Start with the HTTP boundary
FastAPI’s TestClient accepts the application object and exposes familiar request methods. Install the HTTPX dependency required by the client, then write ordinary pytest test functions using normal def and assertions.

Assert status and shape
For an example GET /health endpoint whose contract is {"status": "ok"}, request it through client.get("/health"), assert response.status_code == 200, and compare response.json() with the expected dictionary. That exact comparison catches missing or unexpected fields as well as incorrect values.

Exercise rejection paths
Add separate cases for malformed input, a missing record, and unauthorized access where the endpoint supports them. Assert the documented response contract for each case instead of accepting any client-error status.

Control test state
Create the records each test needs and isolate external services behind test boundaries. A test that succeeds only because another test ran first is unreliable evidence.

Keep async concerns explicit
TestClient requests are synchronous even when the endpoint is async. If a test must directly await asynchronous application code, use the framework’s documented async-testing approach rather than mixing incompatible patterns.