Проверяет понимание различий между unit- и интеграционными тестами и умение выбирать подходящий уровень тестирования для конкретного кода.
Граница между unit- и интеграционными тестами определяется не размером кода, а тем, что именно проверяется: изолированное поведение одной единицы или взаимодействие нескольких частей системы. Unit-тест отвечает на вопрос "правильно ли работает эта функция сама по себе", интеграционный — "правильно ли компоненты работают вместе".
Допустим, есть сервис, который считает скидку и сохраняет заказ в базу.
// Unit-тест: проверяем только логику расчёта, БД замокана
function calculateDiscount(total, user) {
return user.isVip ? total * 0.9 : total;
}
test('VIP получает 10% скидки', () => {
expect(calculateDiscount(100, { isVip: true })).toBe(90);
});
// Интеграционный тест: реально пишем в тестовую БД
async function createOrder(order, db) {
const total = calculateDiscount(order.total, order.user);
return db.orders.insert({ ...order, total });
}
test('заказ сохраняется с учётом скидки', async () => {
const db = await startTestDatabase();
const saved = await createOrder({ total: 100, user: { isVip: true } }, db);
expect(saved.total).toBe(90);
});Иногда граница размыта. Тест класса, который внутри использует другой класс без моков, но без внешних ресурсов, часто называют "социальным unit-тестом" — формально это уже взаимодействие. Если в тесте появляется реальная БД, HTTP-клиент, брокер сообщений или файловая система — это интеграционный тест, даже если проверяется одна функция.
На практике ориентируются на тестовую пирамиду: много быстрых unit-тестов, меньше интеграционных, ещё меньше end-to-end. Unit-тесты дают быструю обратную связь и точную локализацию ошибки, интеграционные ловят проблемы стыковки, которые unit-тесты принципиально не видят.
Итог: применяйте unit-тесты для проверки чистой логики и алгоритмов в изоляции, а интеграционные — когда важно убедиться, что модули, база данных и внешние сервисы корректно работают вместе.