Как отличить модульные тесты от тестов интеграции и в чем их основные различия?
Ответ от нейросети
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. Репозиторий подменён мок-объектом, поэтому тест быстрый и предсказуемый.
Шаги модульного теста:
- Создаётся мок
ICustomerRepository. - Настраивается возврат нужного клиента.
- Создаётся
DiscountServiceс этим мок-объектом. - Вызывается метод
CalculateDiscount. - Проверяется, что результат соответствует ожидаемому.
Для интеграционного теста код обычно сложнее и зависит от конкретной инфраструктуры: это может быть тестовая база, поднятый in-memory server или контейнер с зависимостями. Здесь важно не подмена, а реальное взаимодействие компонентов.
Ключевые моменты:
- Модульные тесты проверяют одну единицу поведения в изоляции.
- Интеграционные тесты проверяют взаимодействие нескольких частей системы.
- Модульные тесты обычно быстрее, проще и стабильнее.
- Интеграционные тесты медленнее, но лучше ловят проблемы конфигурации и связности.
- В модульных тестах часто используют моки и стабы, в интеграционных — реальные зависимости или близкую к реальной среду.
- Хорошая стратегия тестирования обычно включает оба типа: модульные для логики, интеграционные для проверки связей между компонентами.