Spy в Jasmine — это инструмент для отслеживания вызовов функций, позволяющий тестировать взаимодействие между компонентами без изменения их внутренней логики. Spy фиксирует, какие функции были вызваны, с какими аргументами, сколько раз и в каком порядке. Для работы со Spy Jasmine предоставляет мощные matchers, которые помогают проверять поведение функций с высокой детализацией.
Spy создаётся с помощью функций spyOn или
jasmine.createSpy.
let calculator = {
add: (a, b) => a + b
};
spyOn(calculator, 'add');
calculator.add(2, 3);
expect(calculator.add).toHaveBeenCalled();
spyOn(object, 'method') — заменяет метод объекта на
spy, сохраняя возможность отслеживания вызовов.jasmine.createSpy('имя') — создаёт отдельную
функцию-Spy без привязки к объекту.let spyFn = jasmine.createSpy('mySpy');
spyFn('argument');
expect(spyFn).toHaveBeenCalledWith('argument');
toHaveBeenCalledПроверяет, был ли Spy вызван хотя бы один раз.
expect(spy).toHaveBeenCalled();
toHaveBeenCalledTimesПозволяет проверить, сколько раз функция была вызвана.
expect(spy).toHaveBeenCalledTimes(3);
toHaveBeenCalledWithПроверяет, что Spy был вызван с определёнными аргументами хотя бы один раз.
expect(spy).toHaveBeenCalledWith(1, 2, 3);
toHaveBeenCalledOnceWithПодходит для точной проверки, что функция была вызвана один раз с указанными аргументами.
expect(spy).toHaveBeenCalledOnceWith('test');
toHaveBeenCalledBefore и
toHaveBeenCalledAfterИспользуются для проверки порядка вызовов нескольких spy.
let spyA = jasmine.createSpy('A');
let spyB = jasmine.createSpy('B');
spyA();
spyB();
expect(spyA).toHaveBeenCalledBefore(spyB);
expect(spyB).toHaveBeenCalledAfter(spyA);
toHaveBeenCalledWith(jasmine.any(Constructor))Позволяет проверять тип аргумента, не заботясь о его точном значении.
expect(spy).toHaveBeenCalledWith(jasmine.any(Number));
expect(spy).toHaveBeenCalledWith(jasmine.any(String));
toHaveBeenCalledWith(jasmine.objectContaining({...}))Проверяет, что переданный объект содержит указанные ключи и значения, игнорируя остальные свойства.
expect(spy).toHaveBeenCalledWith(jasmine.objectContaining({ id: 1, name: 'Test' }));
Spy можно заставить возвращать определённое значение или бросать исключение.
spyOn(calculator, 'add').and.returnValue(10);
expect(calculator.add(2, 3)).toBe(10);
spyOn(calculator, 'add').and.throwError('Ошибка!');
expect(() => calculator.add(1,2)).toThrowError('Ошибка!');
.and.callThrough() — позволяет вызвать оригинальную
функцию, сохранив возможность отслеживания..and.callFake(fn) — заменяет метод на свою функцию с
кастомной логикой.Jasmine сохраняет всю историю вызовов spy, что позволяет делать комплексные проверки:
spy('first');
spy('second');
expect(spy.calls.count()).toBe(2);
expect(spy.calls.argsFor(0)).toEqual(['first']);
expect(spy.calls.argsFor(1)).toEqual(['second']);
expect(spy.calls.allArgs()).toEqual([['first'], ['second']]);
spy.calls.count() — количество вызовов.spy.calls.argsFor(n) — аргументы конкретного
вызова.spy.calls.allArgs() — массив всех аргументов каждого
вызова.spy.calls.mostRecent() — аргументы последнего
вызова.spy.calls.first() — аргументы первого вызова.Эта функциональность позволяет детально анализировать поведение функций и их взаимодействие с другими объектами.
Spy можно использовать с асинхронными функциями. Например, для проверки вызова после промиса:
let spy = jasmine.createSpy('asyncSpy');
Promise.resolve().then(() => spy());
setTimeout(() => {
expect(spy).toHaveBeenCalled();
}, 0);
Для более точного контроля Jasmine поддерживает fake
timers и async/await.
jasmine.clock().install();
let spy = jasmine.createSpy('delayedSpy');
setTimeout(() => spy(), 1000);
jasmine.clock().tick(1000);
expect(spy).toHaveBeenCalled();
jasmine.clock().uninstall();
spyOn для существующих методов объектов,
чтобы сохранить контекст this.jasmine.createSpy.jasmine.objectContaining и jasmine.any — это
облегчает тестирование частичных совпадений.toHaveBeenCalledBefore/After)
помогает гарантировать правильное взаимодействие модулей в больших
приложениях.Spy matchers в Jasmine позволяют не только проверять результат выполнения функций, но и детально анализировать поведение кода, обеспечивая высокую точность тестов и уверенность в работе приложения.