Что такое заглушка (mock/stub) и зачем она нужна в автоматизированном тестировании?

Ответ

Заглушка (Mock/Stub) — это тестовый двойник (test double), который заменяет реальную зависимость в изолируемом модуле. Она используется для контроля входных данных и поведения зависимостей.

Основные цели:

  • Изоляция тестируемого модуля от внешних систем (БД, API, файловая система).
  • Эмуляция специфического поведения (возврат успешного ответа, ошибки, исключений).
  • Ускорение выполнения тестов за счёт исключения медленных операций.
  • Проверка взаимодействий (был ли метод вызван с нужными аргументами).

Пример использования unittest.mock в Python:

from unittest.mock import Mock

# 1. Создание заглушки для внешнего сервиса
payment_gateway_mock = Mock()

# 2. Настройка поведения: возврат успешного ответа
payment_gateway_mock.process_payment.return_value = {"status": "success", "transaction_id": "txn_123"}

# 3. Настройка поведения: эмуляция ошибки
payment_gateway_mock.process_payment.side_effect = ConnectionError("Service unavailable")

# 4. Использование заглушки в тесте
def test_successful_payment():
    order_service = OrderService(payment_gateway_mock)
    result = order_service.checkout(amount=100.0)

    # Проверка результата
    assert result.is_successful == True
    # Проверка взаимодействия: метод был вызван ровно 1 раз с нужным аргументом
    payment_gateway_mock.process_payment.assert_called_once_with(amount=100.0)

Использование заглушек делает тесты быстрыми, стабильными и сфокусированными на логике тестируемого кода.

Ответ 18+ 🔞

А, ну это же про эти ваши заглушки, блядь! Заглушка, она же мок, она же стаб — это такая тестовая подстава, сука. Ну, типа, подсадная утка, чтобы изолировать модуль от всей остальной ебалы.

Зачем это, нахуй, нужно:

  • Отвязать тестируемый кусок от всей этой внешней хуйни вроде баз данных, апишек или файловой системы. Чтобы не ждать, пока база просрётся, а тест упал.
  • Сымитировать любое поведение, какое душе угодно: успешный ответ, ошибку, исключение — всё, что захочешь, блядь.
  • Ускорить тесты до охуенной скорости, потому что не надо ждать этих долгих операций.
  • Проверить, а вызывалось ли вообще что-то с правильными аргументами, или ты просто так методы дергаешь, как последний распиздяй.

Вот смотри, как на Python'е с unittest.mock это выглядит, ёпта:

from unittest.mock import Mock

# 1. Делаем заглушку для какого-нибудь платёжного шлюза
payment_gateway_mock = Mock()

# 2. Настраиваем её, чтобы возвращала успех
payment_gateway_mock.process_payment.return_value = {"status": "success", "transaction_id": "txn_123"}

# 3. А можно и наоборот — чтобы имитировала обосраный коннект
payment_gateway_mock.process_payment.side_effect = ConnectionError("Service unavailable")

# 4. Используем эту подставу в тесте
def test_successful_payment():
    order_service = OrderService(payment_gateway_mock)
    result = order_service.checkout(amount=100.0)

    # Проверяем, что всё прошло по плану
    assert result.is_successful == True
    # А главное — проверяем, что метод вызвали именно так, как надо, а не абы как
    payment_gateway_mock.process_payment.assert_called_once_with(amount=100.0)

Вот и вся магия, блядь. Тесты становятся быстрыми, как угорелые, стабильными, и ты наконец-то можешь сфокусироваться на логике, а не на том, почему твоя тестовая база опять легла, как последняя шлюха.