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

Для чего нужна заглушка?

1.8 Middle🔥 141 комментариев
#Автоматизация тестирования

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

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

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

Роль заглушки (Stub) в тестировании

Заглушка (Stub) — это ключевой концепт в изоляционном (модульном) тестировании, представляющий собой упрощённую, контролируемую замену реальной зависимости тестируемого модуля. Её основное предназначение — изоляция кода, который мы тестируем (SUT — System Under Test), от внешних или ещё не реализованных компонентов, чтобы сосредоточиться исключительно на его логике.

Основные цели использования заглушек

  • Изоляция тестируемого кода. Заглушка заменяет реальные, сложные зависимости (базы данных, веб-сервисы, файловые системы, сторонние API), которые могут быть медленными, нестабильными или требующими специальных условий для работы. Это позволяет тестам выполняться быстро и детерминировано.
  • Контроль входных данных и состояний. Заглушка программируется на возврат строго определённых, предсказуемых данных (как валидных, так и ошибочных) в ответ на вызовы тестируемого кода. Это позволяет проверить, как SUT ведёт себя в различных сценариях.
  • Верификация косвенных выходов. Хотя основная задача заглушки — предоставление данных, некоторые её виды (например, Spy) могут также фиксировать факт и детали вызова (сколько раз вызван, с какими параметрами), что используется для проверки взаимодействия между модулями.
  • Тестирование до реализации. В методологиях, подобных TDD (Test-Driven Development), заглушки позволяют писать и запускать тесты для модуля, даже когда его зависимости ещё не разработаны. Мы определяем ожидаемый интерфейс (контракт) и создаём его простую реализацию-заглушку.

Отличие от других тестовых двойников (Test Doubles)

Важно не путать заглушку с другими видами тестовых двойников:

  • Mock: Объект, который ожидает определённых вызовов. Он используется для проверки поведения (behavior verification) — убедиться, что SUT корректно взаимодействует с зависимостью. Mock фокусируется на входе для зависимости.
  • Stub: Объект, который возвращает заранее подготовленные данные. Он используется для подмены состояния (state verification) — обеспечить SUT нужными данными. Stub фокусируется на выходе из зависимости.
  • Fake: Упрощённая, но рабочая реализация зависимости (например, база данных в памяти). Она не является ни заглушкой, ни mock'ом в чистом виде, а представляет собой функциональный, но непригодный для продакшена компонент.

Практический пример

Представим сервис PaymentProcessor, который зависит от внешнего PaymentGateway.

# Реальный класс, который мы НЕ хотим использовать в тестах
class RealPaymentGateway:
    def charge(self, amount, token):
        # Реальный HTTP-вызов к платёжному провайдеру
        response = requests.post('https://api.payment.com/charge', ...)
        return response.json()

# Тестируемый сервис
class PaymentProcessor:
    def __init__(self, gateway):
        self.gateway = gateway

    def process_order(self, order):
        # Некоторая бизнес-логика...
        result = self.gateway.charge(order.amount, order.token)
        if result['status'] == 'success':
            order.mark_as_paid()
            return True
        return False

Для юнит-теста PaymentProcessor мы создадим заглушку:

# Заглушка для PaymentGateway
class StubPaymentGateway:
    def __init__(self, fixed_response):
        self.fixed_response = fixed_response

    def charge(self, amount, token):
        # Игнорируем параметры, всегда возвращаем заранее заданный ответ
        return self.fixed_response

# Сам тест
def test_process_order_success():
    # 1. ARRANGE: Подготовка заглушки и тестовых данных
    success_response = {"status": "success", "transaction_id": "123"}
    stub_gateway = StubPaymentGateway(success_response)
    processor = PaymentProcessor(stub_gateway)
    test_order = Order(amount=100, token="tok_abc")

    # 2. ACT: Вызов тестируемого метода
    result = processor.process_order(test_order)

    # 3. ASSERT: Проверка бизнес-логики PaymentProcessor
    assert result is True
    assert test_order.is_paid is True

def test_process_order_failure():
    # Заглушка возвращает ответ об ошибке
    fail_response = {"status": "declined"}
    stub_gateway = StubPaymentGateway(fail_response)
    processor = PaymentProcessor(stub_gateway)
    test_order = Order(amount=100, token="tok_abc")

    result = processor.process_order(test_order)

    assert result is False
    assert test_order.is_paid is False

Вывод

Таким образом, заглушка — это фундаментальный инструмент для создания быстрых, стабильных и детерминированных модульных тестов. Она позволяет тестировать код в полной изоляции, имитируя различные сценарии поведения зависимостей (успех, ошибка, исключения) без необходимости развёртывания реальных внешних систем. Это напрямую способствует повышению качества кода, облегчает отладку и ускоряет процесс разработки.