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

«Что такое заглушка (Stub) в тестировании?» — вопрос из категории Тестирование, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Заглушка (Stub) — это тестовый дублёр (test double), который заменяет реальную зависимость в тестируемой системе, предоставляя предопределённые, фиксированные ответы на вызовы своих методов. Её основная цель — изолировать тестируемый код от внешних сервисов или сложной логики.

Отличие Stub от Mock:

Аспект Stub (Заглушка) Mock (Макет)
Цель Предоставить данные для теста. Проверить взаимодействие (какие методы вызывались, с какими аргументами).
Проверка Не проверяет, как её использовали. Проверяется состояние тестируемой системы. Проверяет, что ожидаемые вызовы были совершены.
Фокус Состояние (State). Поведение (Behavior).

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

Допустим, мы тестируем сервис PriceCalculator, который зависит от IDiscountService.

// Интерфейс зависимости
public interface IDiscountService
{
    decimal GetDiscount(string userId);
}

// Реальная реализация (не используется в тесте)
public class RealDiscountService : IDiscountService
{
    public decimal GetDiscount(string userId)
    {
        // Сложная логика: запрос к БД, вызов внешнего API и т.д.
        return FetchDiscountFromDatabase(userId);
    }
}

// Stub для теста
public class FixedDiscountStub : IDiscountService
{
    private readonly decimal _fixedDiscount;
    public FixedDiscountStub(decimal discount) => _fixedDiscount = discount;

    public decimal GetDiscount(string userId)
    {
        // Игнорируем userId, всегда возвращаем фиксированную скидку
        return _fixedDiscount;
    }
}

// Тест с использованием Stub
[Test]
public void CalculatePrice_WithDiscount_AppliesCorrectly()
{
    // Arrange
    var discountStub = new FixedDiscountStub(10.0m); // Заглушка всегда возвращает 10%
    var calculator = new PriceCalculator(discountStub); // Внедряем заглушку
    decimal basePrice = 100.0m;

    // Act
    decimal finalPrice = calculator.CalculateFinalPrice("user123", basePrice);

    // Assert
    // Проверяем РЕЗУЛЬТАТ работы тестируемого метода, а не то, как вызвали заглушку.
    Assert.AreEqual(90.0m, finalPrice); // 100 - 10%
}

Когда использовать Stub?

  • Когда зависимость возвращает данные, необходимые для выполнения теста (например, конфигурация, курс валют, данные пользователя).
  • Когда нужно симулировать определённое состояние внешней системы (например, «сервис недоступен» — заглушка бросает исключение).
  • Когда реальная зависимость медленная, недетерминированная или её сложно настроить для теста (БД, внешние API).

Главный принцип: Stub делает тест стабильным, быстрым и изолированным, подменяя мир вокруг тестируемого объекта контролируемыми условиями.