Имитация с помощью unittest.mock
Изолируйте тестируемые компоненты, имитируя зависимости.
«Имитация с помощью unittest.mock» — бесплатный урок Python Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Python Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Python Academy содержит 4 уроков всего.
Зачем нужны моки
Моки заменяют реальные зависимости (базы данных, API, файловую систему) управляемыми имитациями, поэтому тесты выполняются быстро, предсказуемо и изолированно.
from unittest.mock import Mock
api = Mock()
api.get_user.return_value = {"id": 1, "name": "Alice"}
result = api.get_user(1)
print(result) # {'id': 1, 'name': 'Alice'}Mock и MagicMock
Mock — базовый класс. MagicMock автоматически настраивает специальные методы, поэтому его можно использовать как итератор, менеджер контекста и т. д.
from unittest.mock import MagicMock
m = MagicMock()
m.__len__.return_value = 5
print(len(m)) # 5
m.__iter__.return_value = iter([1, 2, 3])
for x in m:
print(x)patch как декоратор
Используйте @patch, чтобы на время теста заменить объект в модуле моком.
from unittest.mock import patch
def get_data():
import requests
return requests.get("https://api.example.com").json()
@patch("requests.get")
def test_get_data(mock_get):
mock_get.return_value.json.return_value = {"key": "value"}
result = get_data()
assert result == {"key": "value"}patch как менеджер контекста
Используйте patch() как менеджер контекста для более локального мокирования.
from unittest.mock import patch
def test_open():
with patch("builtins.open", create=True) as mock_open:
mock_open.return_value.__enter__.return_value.read.return_value = "data"
with open("file.txt") as f:
assert f.read() == "data"patch.object
patch.object(target, attribute) заменяет определённый атрибут существующего объекта или класса.
from unittest.mock import patch
import mymodule
def test_method():
with patch.object(mymodule.MyClass, "fetch", return_value=42):
obj = mymodule.MyClass()
assert obj.fetch() == 42Проверка вызовов
Моки записывают каждый вызов. Используйте assert_called_once_with, assert_called_with и call_count, чтобы проверить поведение.
from unittest.mock import Mock
send = Mock()
send("hello", to="alice")
send.assert_called_once_with("hello", to="alice")
print(send.call_count) # 1Возвращаемое значение и побочный эффект
Установите return_value, чтобы управлять возвращаемым моком значением. Используйте side_effect, чтобы возбуждать исключения или возвращать разные значения при последовательных вызовах.
from unittest.mock import Mock
m = Mock(side_effect=[1, 2, ValueError("done")])
print(m()) # 1
print(m()) # 2
m() # raises ValueErrorspec: типобезопасные моки
Передайте spec=MyClass, чтобы ограничить мок атрибутами, существующими в настоящем классе.
from unittest.mock import Mock
class Calc:
def add(self, a, b): return a + b
m = Mock(spec=Calc)
m.add(1, 2) # OK
# m.subtract(1, 2) # AttributeError: Mock does not have 'subtract'patch.dict
Используйте patch.dict, чтобы временно изменить словарь (например, переменные окружения или конфигурации уровня модуля).
from unittest.mock import patch
import os
def test_env():
with patch.dict(os.environ, {"DEBUG": "true"}):
assert os.environ["DEBUG"] == "true"
assert "DEBUG" not in os.environМокирование в pytest с помощью pytest-mock
pytest-mock предоставляет фикстуру mocker, которая оборачивает unittest.mock и автоматически выполняет очистку после каждого теста.
# pip install pytest-mock
def test_service(mocker):
mocker.patch("mymodule.requests.get", return_value=mocker.Mock(
json=lambda: {"status": "ok"}
))
from mymodule import call_api
assert call_api()["status"] == "ok"AsyncMock для корутин
Используйте AsyncMock для мокирования асинхронных функций, которые вызываются с ожиданием.
from unittest.mock import AsyncMock, patch
import asyncio
async def fetch():
import httpx
async with httpx.AsyncClient() as c:
r = await c.get("https://example.com")
return r.json()
def test_fetch():
with patch("httpx.AsyncClient.get", new_callable=AsyncMock) as m:
m.return_value.json.return_value = {"ok": True}
result = asyncio.run(fetch())
assert result["ok"] is TrueПроверка
Какой атрибут нужно установить у Mock, чтобы управлять значением, возвращаемым при вызове?
Итоги
unittest.mock предоставляет Mock, MagicMock, patch и AsyncMock. Используйте return_value и side_effect, чтобы управлять поведением, а методы проверок — чтобы убедиться, как были вызваны моки.
Часто задаваемые вопросы
Урок «Имитация с помощью unittest.mock» бесплатный?
Да — полный текст урока «Имитация с помощью unittest.mock» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Python Academy, подпишись на CoddyKit PRO. Курс Python Academy содержит 4 уроков всего.
Чему я научусь в уроке «Имитация с помощью unittest.mock»?
Изолируйте тестируемые компоненты, имитируя зависимости. Ты практикуешь Python Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Python Academy?
Предыдущий опыт не требуется. Python Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Имитация с помощью unittest.mock»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Python Academy?
Да. Каждый урок Python Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Написание первых тестов pytest
- Фикстуры и настройка/очистка
- Параметризация и покрытие тестами
- Имитация с помощью unittest.mock