Мок модулей и шпионы
Урок объясняет, как заменить целый модуль моком и как шпионить за реальным методом.
jest.mock подменяет весь модуль заглушками, а jest.spyOn оборачивает существующий метод, отслеживая его вызовы.
Зачем мокать модули
Тестируемая функция часто зависит от других модулей: HTTP-клиента, базы, файловой системы. Дёргать их по-настоящему — медленно и ненадёжно. jest.mock заменяет модуль фейком, чтобы тест проверял только вашу логику.
jest.mock: подмена модуля
// userService.js использует api.js
const api = require('./api');
async function getUserName(id) {
const user = await api.fetchUser(id);
return user.name.toUpperCase();
}
module.exports = { getUserName };В тесте подменяем api целиком — настоящего сетевого запроса не будет:
jest.mock('./api'); // авто-мок: все экспорты становятся jest.fn()
const api = require('./api');
const { getUserName } = require('./userService');
test('возвращает имя в верхнем регистре', async () => {
api.fetchUser.mockResolvedValue({ name: 'аня' });
const name = await getUserName(1);
expect(name).toBe('АНЯ');
expect(api.fetchUser).toHaveBeenCalledWith(1);
});Так мы проверили логику getUserName в полной изоляции от сети.
jest.spyOn: наблюдение за методом
Иногда не нужно полностью подменять — достаточно проследить за реальным методом (и при желании временно подменить его поведение). Для этого есть spyOn:
const logger = {
save(msg) { /* пишет в файл */ }
};
test('логирует сообщение об ошибке', () => {
const spy = jest.spyOn(logger, 'save');
handleError(logger, 'сбой');
expect(spy).toHaveBeenCalledWith('сбой');
spy.mockRestore(); // вернуть оригинал
});Частый приём — заглушить шумный console.log в тесте: jest.spyOn(console, 'log').mockImplementation(() => {}).
Чистка моков между тестами
Чтобы счётчики вызовов не «протекали» между тестами, их сбрасывают:
afterEach(() => {
jest.clearAllMocks(); // сбрасывает mock.calls у всех моков
});Есть и опция clearMocks: true в конфиге Jest, делающая это автоматически.
mock против spy — кратко
| Инструмент | Что делает |
jest.fn() | создаёт новую мок-функцию с нуля |
jest.mock('mod') | подменяет весь модуль заглушками |
jest.spyOn(obj, 'm') | оборачивает существующий метод, можно вернуть оригинал |
Итог
jest.mock('./api')заменяет модуль авто-моками — изоляция от сети/диска.- Поведение мока задают
mockResolvedValue/mockReturnValue. jest.spyOnследит за реальным методом,mockRestoreвозвращает оригинал.- Между тестами моки чистят (
clearAllMocks) ради изоляции.