Jasmine — это фреймворк для тестирования JavaScript, ориентированный на поведение кода (Behavior-Driven Development, BDD). Одной из ключевых возможностей Jasmine является отслеживание вызовов функций и получение информации о них, что позволяет тестировать взаимодействие компонентов, а не только конечный результат. Эта функциональность реализуется через spies.
Spy в Jasmine — это объект, который «подставляется» вместо функции и регистрирует каждый её вызов, аргументы, количество вызовов и возвращаемые значения. Spy может быть создан:
let obj = {
method: function(a, b) {
return a + b;
}
};
spyOn(obj, 'method');
obj.method(1, 2);
В этом примере:
spyOn(obj, 'method') превращает method в
spy.obj.method() фиксируется.Jasmine предоставляет встроенные методы для анализа spy:
toHaveBeenCalled() Проверяет, был
ли spy вызван хотя бы один раз.
expect(obj.method).toHaveBeenCalled();toHaveBeenCalledTimes(number)
Сравнивает количество вызовов с ожидаемым числом.
expect(obj.method).toHaveBeenCalledTimes(2);toHaveBeenCalledWith(...args)
Проверяет, вызывался ли spy с указанными аргументами.
expect(obj.method).toHaveBeenCalledWith(1, 2);calls Свойство spy, предоставляющее
подробный интерфейс для анализа вызовов:
calls.any() — возвращает
true, если spy был вызван хотя бы один раз.calls.count() — возвращает количество
вызовов.calls.argsFor(index) — возвращает
массив аргументов конкретного вызова по индексу.calls.allArgs() — массив аргументов
всех вызовов.calls.all() — массив объектов
CallInfo с полной информацией о каждом вызове.calls.mostRecent() — объект
CallInfo для последнего вызова.calls.first() — объект
CallInfo для первого вызова.calls.reset() — сбрасывает историю
вызовов.Пример использования calls:
obj.method(1, 2);
obj.method(3, 4);
console.log(obj.method.calls.count()); // 2
console.log(obj.method.calls.argsFor(0)); // [1, 2]
console.log(obj.method.calls.mostRecent().args); // [3, 4]
Spy позволяет не только отслеживать вызовы, но и подменять реальное поведение функции:
and.callThrough() Выполняет
оригинальную функцию при вызове spy:
spyOn(obj, 'method').and.callThrough();
obj.method(1, 2); // вызов реальной функцииand.returnValue(value) Возвращает
указанное значение вместо оригинальной функции:
spyOn(obj, 'method').and.returnValue(42);
obj.method(1, 2); // всегда вернет 42and.callFake(fakeFunction)
Позволяет заменить функцию пользовательской реализацией:
spyOn(obj, 'method').and.callFake((a, b) => a * b);
obj.method(3, 4); // вернет 12and.throwError(message)
Подбрасывает ошибку при вызове spy:
spyOn(obj, 'method').and.throwError('Ошибка вызова');
expect(() => obj.method()).toThrowError('Ошибка вызова');Иногда важно не только знать, был ли вызов, но и порядок
вызовов нескольких функций. Для этого можно использовать
calls.all():
spyOn(obj, 'method1');
spyOn(obj, 'method2');
obj.method1();
obj.method2();
obj.method1();
const calls = obj.method1.calls.all();
console.log(calls.length); // 2
console.log(calls[0].args); // аргументы первого вызова method1
and.callThrough() оригинальная логика не выполняется. Это
критично при тестировании побочных эффектов.calls.reset())
полезен при тестировании нескольких сценариев в одном it
блоке.spyOn; требуется экспортировать функцию
или использовать jasmine.createSpy().Для функций, которые не существуют в объекте, можно создать чистый spy:
let spyFunc = jasmine.createSpy('mySpy');
spyFunc(1, 2);
expect(spyFunc).toHaveBeenCalledWith(1, 2);
createSpy также поддерживает:
and.returnValue()and.callFake()and.throwError()Spy используется для:
Пример проверки callback:
function fetchData(callback) {
setTimeout(() => {
callback('data');
}, 100);
}
it('вызывает callback с данными', (done) => {
const callback = jasmine.createSpy('callback').and.callFake((data) => {
expect(data).toBe('data');
done();
});
fetchData(callback);
});
Этот набор инструментов делает Jasmine мощным средством контроля и анализа вызовов функций, позволяя писать тесты, которые проверяют не только результат, но и взаимодействие компонентов в приложении.