Короткий ответ
Mock — это объект-заглушка, который подменяет реальную зависимость, чтобы тест не обращался к сети, базе данных или окружению. unittest.mock даёт mock-объекты и декоратор patch() для подмены атрибутов, а фикстура monkeypatch из pytest безопасно меняет атрибуты, элементы словарей и переменные окружения с автоматическим откатом.
Как это работает подробнее
Внешние зависимости не вызываются по-настоящему: вместо них в тест подставляются заглушки с известным поведением, что делает тест быстрым и детерминированным.
- Mock-объекты.
unittest.mockизбавляет от ручного создания стабов: после действия проверяют, какие методы и с какими аргументами вызывались, например черезmock.method.assert_called_with(...). - Настройка поведения. Заглушке задают возвращаемое значение через
return_valueили заставляют вызов бросить исключение черезside_effect. - Патчинг. Декоратор
patch()подменяет атрибуты модулей и классов в пределах области действия теста. - Фикстура monkeypatch. В pytest меняет атрибуты, элементы словарей и переменные окружения методами
setattr(),setitem(),setenv()и другими, а такжеsys.path. - Автоматический откат. Все изменения
monkeypatchвозвращаются назад после завершения теста или фикстуры.
Пример кода
Подмена Path.home через monkeypatch
from pathlib import Path
def test_home(monkeypatch):
monkeypatch.setattr(Path, 'home', lambda: Path('/abc'))
assert Path.home() == Path('/abc')Что использовать на практике
- Внешние сервисы. Подменяй сетевые вызовы, базу данных и чтение окружения, чтобы тесты не зависели от внешнего мира.
- Проверка вызовов. Используй mock, когда нужно убедиться, что метод вызван с правильными аргументами.
- monkeypatch в pytest. Применяй для точечной подмены атрибутов и переменных окружения без ручного восстановления.
- Интеграционные тесты. Настоящие вызовы внешних систем оставляй отдельно и в небольшом количестве.
Подводные камни
- Избыточное моканье. Подмена всего подряд делает тест хрупким и оторванным от реального поведения кода.
- Неверная цель патча. Патчить нужно то место, где объект используется, а не то, где он создаётся, иначе подмена не сработает.
- Ручные изменения. Подмена без
patch()илиmonkeypatchрискует оставить «грязное» окружение для других тестов.
Как отвечать на собеседовании
- Объясни, что такое mock и зачем подменять внешние зависимости → сравни
unittest.mockи фикстуруmonkeypatchиз pytest → покажи пример подмены атрибута → подчеркни автоматический откат изменений после теста.