← Назад к вопросам

Что такое Mock?

1.0 Junior🔥 242 комментариев
#Автоматизация тестирования

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое Mock (Мок, Заглушка)?

В контексте автоматизированного тестирования, особенно модульного (Unit Testing), Mock — это специальный объект-заглушка, который имитирует поведение реального зависимого компонента системы, но полностью контролируется тестом. Его основная цель — изолировать тестируемый модуль (SUT - System Under Test) от внешних зависимостей, таких как базы данных, веб-сервисы, файловые системы или сложные внутренние классы.

Ключевые цели использования Mock-объектов:

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

Отличие Mock от других типов тестовых дублеров (Test Doubles)

Часто термин "Mock" используют обобщенно, но в классификации (по Мартину Фаулеру и Дж. М. Гранту) есть важные нюансы:

  • Stub (Стаб): Простейшая заглушка, предоставляющая предопределенные ответы на вызовы во время теста. Не отслеживает взаимодействия.
  • Spy (Шпион): Обертка вокруг реального объекта или стаб, которая регистрирует информацию о вызовах для последующей проверки.
  • Mock (Мок): Объект с предварительно заданными ожиданиями (expectations). Он не только возвращает данные, но и активно проверяет, соответствуют ли вызовы этим ожиданиям. Провал теста происходит внутри Mock-объекта, если ожидание не выполнено.
  • Fake (Фейк): Упрощенная, но рабочая реализация зависимости (например, база данных в памяти), пригодная для тестирования, но не для продакшена.

Таким образом, ключевая характеристика именно Mock — это наличие и проверка ожиданий (expectations) о взаимодействии.

Практический пример на Python (с использованием unittest.mock)

Допустим, мы тестируем сервис NotificationService, который отправляет уведомления через внешний EmailGateway.

# production_code.py
class EmailGateway:
    def send(self, to, subject, body):
        # Сложная логика отправки по SMTP
        pass

class NotificationService:
    def __init__(self, email_gateway):
        self.gateway = email_gateway

    def send_welcome_email(self, user_email):
        message = "Добро пожаловать!"
        self.gateway.send(user_email, "Приветствие", message)
# test_code.py
import unittest
from unittest.mock import Mock, call
from production_code import NotificationService

class TestNotificationService(unittest.TestCase):

    def test_send_welcome_email_calls_gateway_correctly(self):
        # 1. ARRANGE: Создаем Mock-объект для замены EmailGateway
        mock_email_gateway = Mock(spec=EmailGateway) # spec гарантирует соответствие интерфейсу

        # Настраиваем mock (опционально, если нужно вернуть значение)
        # mock_email_gateway.send.return_value = "OK"

        service = NotificationService(mock_email_gateway)

        # 2. ACT: Выполняем тестируемый метод
        test_email = "user@example.com"
        service.send_welcome_email(test_email)

        # 3. ASSERT: Верифицируем ожидания взаимодействия с Mock
        # Проверяем, что метод send был вызван РОВНО ОДИН раз
        mock_email_gateway.send.assert_called_once()
        # Проверяем, что метод send был вызван с КОНКРЕТНЫМИ АРГУМЕНТАМИ
        mock_email_gateway.send.assert_called_once_with(
            test_email,
            "Приветствие",
            "Добро пожаловать!"
        )
        # Альтернативная, более детальная проверка
        expected_call = call(test_email, "Приветствие", "Добро пожаловать!")
        self.assertIn(expected_call, mock_email_gateway.send.mock_calls)

Когда стоит и не стоит использовать Mock

Используйте Mock:

  • Для изоляции модульных тестов.
  • Для тестирования сложных сценариев взаимодействия (например, порядок вызовов).
  • Для симуляции редких или ошибочных состояний зависимостей (сетевые сбои, исключения).

Избегайте чрезмерного использования Mock:

  • Не мокайте то, что не является внешней зависимостью (например, простые структуры данных).
  • Избыточное мокирование может привести к хрупким тестам, которые проверяют не поведение, а реализацию.
  • Если можно использовать Fake (например, базу данных в памяти) для интеграционного тестирования, это часто предпочтительнее.

Заключение

Mock — это мощный инструмент в арсенале QA- и Software-инженера, направленный на создание быстрых, стабильных и сфокусированных модульных тестов. Его правильное применение позволяет добиться высокой покрытия кода (code coverage) и уверенности в корректности отдельных компонентов системы, прежде чем они будут интегрированы. Однако важно понимать его место среди других типов Test Doubles и применять осознанно, чтобы тесты оставались релевантными и поддерживаемыми.

Что такое Mock? | PrepBro