0Pricing
Python Academy · Урок

Имитация с помощью 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 ValueError

spec: типобезопасные моки

Передайте 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 — локальная установка не требуется.

Все уроки этого курса

  1. Написание первых тестов pytest
  2. Фикстуры и настройка/очистка
  3. Параметризация и покрытие тестами
  4. Имитация с помощью unittest.mock
← Назад к Python Academy