PRO

Как писать тесты для FastAPI с TestClient и pytest?

TestClient позволяет отправлять запросы к FastAPI-приложению в тестах без запуска отдельного HTTP-сервера. В связке с pytest обычно создают client fixture, проверяют status code и тело ответа, а зависимости базы данных и аутентификации переопределяют через app.dependency_overrides.
Подробный ответ

Базовый тест endpoint

Для синхронных тестов создают объект TestClient, передавая в него FastAPI-приложение. Его интерфейс похож на HTTP-клиент: можно вызвать get(), post() и проверить ответ через обычные assertions pytest.

from fastapi.testclient import TestClient
from app.main import app

client = TestClient(app)


def test_read_healthcheck():
    response = client.get('/health')

    assert response.status_code == 200
    assert response.json() == {'status': 'ok'}

Fixture для клиента

В большом проекте client обычно создают как pytest fixture в conftest.py.

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


@pytest.fixture
def client():
    with TestClient(app) as test_client:
        yield test_client

Контекстный менеджер особенно важен, если приложение использует lifespan: он запускает и корректно завершает ресурсы приложения во время теста.

Переопределение dependencies

Тесты не должны зависеть от production-базы, внешних API или реальной аутентификации. FastAPI позволяет заменить dependency тестовой реализацией через app.dependency_overrides.

def get_test_db():
    yield test_session


app.dependency_overrides[get_db] = get_test_db


def test_create_article(client):
    response = client.post(
        '/articles',
        json={'title': 'Test article', 'text': 'Content'},
    )

    assert response.status_code == 201
    assert response.json()['title'] == 'Test article'


app.dependency_overrides.clear()

Что проверять

  • status code и формат JSON-ответа;

  • валидацию некорректных входных данных;

  • аутентификацию и права доступа;

  • ошибки доменной логики;

  • побочные эффекты в базе и внешних интеграциях через mocks или тестовые реализации.

Как ответить на собеседовании

Я использую TestClient и pytest для вызова endpoints без отдельного сервера, проверяю status code и JSON. Для изоляции тестов переопределяю dependencies базы, текущего пользователя и внешних клиентов через app.dependency_overrides; если есть lifespan, создаю TestClient через context manager.

Оцени свой прогресс

Честно оцени своё понимание этого вопроса, чтобы мы могли построить твой учебный трек максимально эффективно.
Читать в блоге