FastAPI: From Basics to Production · Testing FastAPI Applications

Testing with TestClient and pytest

Write fast API tests that run in-process.

fastapi.testclient.TestClient (built on httpx) calls your app in-process — no server needed. Use it with pytest fixtures, assert on status codes and JSON, and use it as a context manager (with TestClient(app) as client) so lifespan startup/shutdown run. Organize fixtures in conftest.py.

# tests/conftest.py
import pytest
from fastapi.testclient import TestClient
from app.main import app


@pytest.fixture
def client():
    with TestClient(app) as c:      # runs lifespan
        yield c


# tests/test_health.py
def test_health(client):
    resp = client.get("/health")
    assert resp.status_code == 200
    assert resp.json() == {"status": "ok"}


def test_validation_error(client):
    resp = client.get("/books/not-a-number")
    assert resp.status_code == 422
    assert resp.json()["detail"][0]["loc"] == ["path", "book_id"]

Common pitfalls

  • Not using the context manager, so lifespan resources aren't created.
  • Tests depending on each other's data.
  • Only testing happy paths.

Key points

  • In-process testing with TestClient
  • Context manager runs lifespan
  • Test validation and error paths

Further reading: FastAPI: Testing

Practice questions

Why use with TestClient(app) as client?

Answer

Entering the context triggers lifespan startup (creating pools/clients) and exiting runs shutdown, matching production behavior.

Does TestClient need a running server?

Answer

No. It sends requests directly to the ASGI app in-process, making tests fast.

Open in the app to mark lessons complete, take notes and track your progress.