Что такое mock-объекты и зачем их использовать в unit-тестах

Ответ

Mock-объекты (моки) — это "поддельные" объекты, которые имитируют поведение реальных зависимостей в контролируемых условиях. Они являются ключевым инструментом для изоляции тестируемого компонента.

Основная цель их использования — заменить внешние зависимости (например, базу данных, внешнее API, файловую систему), чтобы:

  • Изолировать тест: Убедиться, что тест проверяет только логику конкретного модуля, а не его зависимостей.
  • Ускорить выполнение тестов: Избежать медленных операций, таких как сетевые запросы или чтение с диска.
  • Сделать тесты детерминированными: Контролировать возвращаемые значения и ошибки, делая результат теста предсказуемым.
  • Тестировать сложные сценарии: Эмулировать специфические состояния или ошибки, которые трудно воспроизвести с реальными объектами (например, отказ сети).

Пример с unittest.mock в Python:

Предположим, у нас есть функция, которая получает данные о погоде с внешнего API.

import requests

def get_weather_forecast():
    response = requests.get("http://api.weather.com/forecast")
    response.raise_for_status() # Вызовет исключение для плохих статусов
    return response.json()["temperature"]

Тест с использованием patch для подмены requests.get:

from unittest.mock import patch

def test_get_weather_forecast_success():
    # Создаем mock-объект для ответа API
    mock_response = {"temperature": 25}

    # patch заменяет requests.get на mock-объект внутри блока with
    with patch('requests.get') as mock_get:
        # Настраиваем, что должен вернуть наш mock
        mock_get.return_value.json.return_value = mock_response
        mock_get.return_value.raise_for_status.return_value = None

        # Вызываем нашу функцию
        temperature = get_weather_forecast()

        # Проверяем результат
        assert temperature == 25
        # Проверяем, что requests.get был вызван с правильным URL
        mock_get.assert_called_once_with("http://api.weather.com/forecast")

Ключевые инструменты в Python:

  • unittest.mock: Стандартная библиотека для мокинга.
  • pytest-mock: Популярный плагин для pytest, предоставляющий удобную фикстуру mocker.