Как написать тест для класса, который получает данные из базы, обрабатывает их бизнес-логикой и возвращает результат на endpoint
Что проверяют
Умеете ли вы выбрать уровень теста под задачу, а не мокать всё подряд. Интервьюер ждёт разделения: бизнес-логику проверяют юнит-тестами, работу с базой интеграционно, эндпоинт через тестовый клиент. Следом спрашивают, как изолировать тесты с настоящей базой друг от друга.
Как отвечать
Главный ход: сначала сделайте код тестируемым. Если класс сам открывает подключение, тест превратится в гирлянду patch. Разделите код на репозиторий (доступ к данным), сервис (логика) и эндпоинт, а зависимости передавайте через конструктор или Depends в FastAPI.
- юнит-тест логики: в
pytestотдайте сервису фейковый репозиторий, простой класс илиMock(spec=Repo), и проверяйте результат, а не порядок вызовов. Для асинхронного кода естьAsyncMockи плагинpytest-asyncioилиanyio; - параметризация:
@pytest.mark.parametrizeдля пустых данных, одной записи, граничных значений и ошибочного ввода; - интеграционный тест репозитория: настоящая база в Docker через
testcontainers, схема из миграций Alembic, каждый тест внутри транзакции с откатом в фикстуре. SQLite вместо PostgreSQL подходит плохо: другие типы, другие блокировки, нетjsonb; - тест эндпоинта:
TestClientилиhttpx.AsyncClientсASGITransport, подмена зависимостей черезapp.dependency_overrides. Проверяйте код ответа, схему тела и поведение на ошибках; - если стек Django:
pytest-django, маркерdjango_dbиAPIClientиз DRF, каждый тест по умолчанию выполняется в транзакции с откатом.
Про patch скажите отдельно: подменять имя нужно там, где его ищут, а не там, где оно объявлено. Если сервис сделал from app.db import get_session, патчить надо app.services.get_session.
Где спотыкаются
Мокают базу и проверяют, что мок вернул то, что в него положили. Такой тест не ловит ни одной ошибки, зато ломается при любом рефакторинге.
Ставят patch не на тот путь, и тест незаметно ходит в настоящую базу или падает с непонятной ошибкой. Внедрение зависимостей снимает этот класс проблем целиком.
Делят базу между тестами без очистки, и результат зависит от порядка запуска. Спасают транзакция с откатом или отдельная схема на прогон.