Sobes.tech
Назад к вопросам
Junior — Middle
64

Как отличить модульные тесты от тестов интеграции и в чем их основные различия?

Ответ от нейросети

sobes.tech AI

Что хотят услышать интервьюеры:

Модульные тесты проверяют маленький изолированный кусок кода, обычно одну функцию или метод, без зависимостей от внешних систем. Интеграционные тесты проверяют, что несколько частей приложения работают вместе корректно. Главное различие — в уровне изоляции, скорости выполнения и цели теста.

Определение:

Модульный тест фокусируется на поведении одного компонента и стремится исключить влияние внешних зависимостей: базы данных, сети, файловой системы, времени, очередей и т.д. Для этого зависимости часто подменяют моками или стабыми.

Интеграционный тест проверяет взаимодействие реальных компонентов между собой. В C# это может быть связка сервиса с репозиторием, доступ к БД через ORM, HTTP-клиент к тестовому серверу или работа нескольких слоёв приложения вместе.

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

Допустим, есть сервис расчёта скидки и отдельный репозиторий для чтения данных клиента.

public class DiscountService
{
    private readonly ICustomerRepository _repository;

    public DiscountService(ICustomerRepository repository)
    {
        _repository = repository;
    }

    public decimal CalculateDiscount(int customerId)
    {
        var customer = _repository.GetById(customerId);

        if (customer.IsVip)
            return 0.2m;

        return 0.05m;
    }
}

Модульный тест проверяет только логику DiscountService, подменяя репозиторий:

[Fact]
public void CalculateDiscount_ReturnsVipDiscount_ForVipCustomer()
{
    var repository = new Mock<ICustomerRepository>();
    repository.Setup(r => r.GetById(1))
              .Returns(new Customer { IsVip = true });

    var service = new DiscountService(repository.Object);

    var result = service.CalculateDiscount(1);

    Assert.Equal(0.2m, result);
}

Интеграционный тест проверяет реальную связку, например сервис + настоящая БД или сервис + HTTP endpoint, чтобы убедиться, что данные реально сохраняются и читаются.

Пояснение кода:

В примере модульный тест не зависит от базы данных и проверяет только бизнес-логику внутри CalculateDiscount. Репозиторий подменён мок-объектом, поэтому тест быстрый и предсказуемый.

Шаги модульного теста:

  1. Создаётся мок ICustomerRepository.
  2. Настраивается возврат нужного клиента.
  3. Создаётся DiscountService с этим мок-объектом.
  4. Вызывается метод CalculateDiscount.
  5. Проверяется, что результат соответствует ожидаемому.

Для интеграционного теста код обычно сложнее и зависит от конкретной инфраструктуры: это может быть тестовая база, поднятый in-memory server или контейнер с зависимостями. Здесь важно не подмена, а реальное взаимодействие компонентов.

Ключевые моменты:

  • Модульные тесты проверяют одну единицу поведения в изоляции.
  • Интеграционные тесты проверяют взаимодействие нескольких частей системы.
  • Модульные тесты обычно быстрее, проще и стабильнее.
  • Интеграционные тесты медленнее, но лучше ловят проблемы конфигурации и связности.
  • В модульных тестах часто используют моки и стабы, в интеграционных — реальные зависимости или близкую к реальной среду.
  • Хорошая стратегия тестирования обычно включает оба типа: модульные для логики, интеграционные для проверки связей между компонентами.