Jest: spyOn
jest.spyOnсоздаёт spy (шпиона) — обёртку над существующим методом объекта, которая отслеживает вызовы и при необходимости подменяет реализацию, сохраняя возможность восстановления оригинала.
Зачем нужно
В отличие от jest.fn, spyOn работает с уже существующими методами — позволяет следить за ними или временно заменить, не ломая весь модуль. Это ключевой инструмент для тестирования side effects: отправки аналитики, вызова console.error, записи в localStorage.
Где используется
- Проверка, что метод был вызван с нужными аргументами
- Подмена
console.error/console.warnчтобы тест не шумел в stdout - Мокирование метода класса или объекта без замены всего модуля
- Временная подмена реализации с последующим восстановлением (
mockRestore)
Основной контент
Базовый spy — только слежка
import * as mathUtils from './mathUtils';
test('вызывает calculateTax при оформлении заказа', () => {
const spy = jest.spyOn(mathUtils, 'calculateTax');
placeOrder({ amount: 1000 });
expect(spy).toHaveBeenCalledTimes(1);
expect(spy).toHaveBeenCalledWith(1000);
spy.mockRestore(); // восстанавливаем оригинал
});
Подмена реализации
test('обрабатывает ошибку fetch', async () => {
const spy = jest.spyOn(global, 'fetch').mockResolvedValue({
ok: false,
status: 500,
json: async => ({ error: 'Server error' }),
});
await expect(getUser(1)).rejects.toThrow('Server error');
spy.mockRestore();
});
Spy на console
test('логирует ошибку при невалидном вводе', () => {
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
validateForm({ name: '' });
expect(consoleSpy).toHaveBeenCalledWith('Name is required');
consoleSpy.mockRestore();
});
Spy на метод класса
import { UserService } from './UserService';
test('вызывает save при создании пользователя', async () => {
const service = new UserService();
const saveSpy = jest.spyOn(service, 'save').mockResolvedValue({ id: 1 });
await service.createUser({ name: 'Alice' });
expect(saveSpy).toHaveBeenCalledWith({ name: 'Alice' });
});
Проверка аргументов
expect(spy).toHaveBeenCalledWith(expect.objectContaining({ id: 1 }));
expect(spy).toHaveBeenLastCalledWith('error', 'message');
expect(spy).toHaveBeenNthCalledWith(2, 'second call arg');
Восстановление в afterEach
afterEach(() => {
jest.restoreAllMocks; // восстанавливает все spyOn
});
Частые ошибки
- Забытый
mockRestore— spy остаётся активным и ломает другие тесты; используйjest.restoreAllMocksвafterEach spyOnна ES-модуль по умолчанию — не работает напрямую; нужно импортировать* as moduleи следить за свойствомmockImplementationвместоmockReturnValue— для простого возврата значения достаточноmockReturnValue;mockImplementationнужна только для сложной логики- Проверка
toHaveBeenCalledбез вызова кода — убедись, что тестируемая функция реально вызывает отслеживаемый метод