Learn / Frameworks / FastAPI / Testing with TestClient

FastAPI · Lesson 9 of 15

Testing with TestClient

pytest fixtures, dependency overrides and asserting on status codes.

  • Intermediate
  • 16 min read
  • 3 objectives

Before this lessonLesson 8: Uploads, Streaming and Static Files

What you will learn

  • Override a dependency
  • Test auth headers
  • Use a test database

Your Progress

0 of 15 lessons 0%

  • Lessons0 / 15
  • Completed0
  • Est. time left~ 4 hours

Create a free account to keep your progress on every device.

TestClient runs your app in-process: no real port, real dependency injection, and you can swap the database for a sqlite memory file.

A fixture

import pytest
from fastapi.testclient import TestClient
from main import app, get_db

@pytest.fixture
def client():
    def override_db():
        yield TestingSession()
    app.dependency_overrides[get_db] = override_db
    with TestClient(app) as c:
        yield c
    app.dependency_overrides.clear()

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

Auth headers

def test_me_requires_token(client):
    assert client.get("/me").status_code == 401

def test_me_ok(client):
    token = client.post("/token", data={"username": "ada@example.com", "password": "secret"}).json()["access_token"]
    r = client.get("/me", headers={"Authorization": f"Bearer {token}"})
    assert r.status_code == 200
    assert r.json()["email"] == "ada@example.com"

Async tests

If you need to await inside a test, use httpx.AsyncClient with ASGITransport and pytest-asyncio. For most APIs, the sync TestClient is enough.

Up next · Lesson 10Settings with pydantic-settingsLoad config from the environment, keep secrets out of code and cache settings.