Jasmine предоставляет мощный инструмент для изоляции и тестирования
функций — spies. Среди различных способов создания
spies особое место занимает standalone spy, который не
привязан к объекту и создаётся напрямую с помощью метода
createSpy. Этот подход полезен, когда необходимо
отслеживать вызовы функций, не интегрированных в конкретный объект, или
при тестировании callback-функций и независимых модулей.
createSpyФункция createSpy создаёт объект spy, который ведёт учёт
всех вызовов, аргументов и контекста исполнения:
const mySpy = jasmine.createSpy('mySpy');
'mySpy') используется в
отчетах тестов и для удобного вывода ошибок.mySpy.calls.count() показывает, сколько раз функция была
вызвана.mySpy();
mySpy();
console.log(mySpy.calls.count()); // 2
Jasmine предоставляет набор методов для проверки вызовов spy:
toHaveBeenCalled() — проверка, был ли вызов
функции;toHaveBeenCalledTimes(n) — проверка числа вызовов;toHaveBeenCalledWith(...args) — проверка аргументов
конкретного вызова;toHaveBeenCalledOnceWith(...args) — проверка одного
вызова с определёнными аргументами.Пример:
const callback = jasmine.createSpy('callback');
callback(1, 2);
expect(callback).toHaveBeenCalled();
expect(callback).toHaveBeenCalledTimes(1);
expect(callback).toHaveBeenCalledWith(1, 2);
По умолчанию standalone spy ничего не делает, кроме учёта вызовов.
Для тестов часто необходимо задать конкретное поведение. Для этого
используется and.callFake, and.returnValue,
and.callThrough и and.throwError:
const spyWithReturn = jasmine.createSpy('spyWithReturn').and.returnValue(42);
console.log(spyWithReturn()); // 42
const spyWithFake = jasmine.createSpy('spyWithFake').and.callFake((a, b) => a + b);
console.log(spyWithFake(3, 4)); // 7
and.returnValue(value) — spy всегда возвращает
указанное значение;and.callFake(fn) — задаёт пользовательскую
реализацию;and.throwError(message) — вызывает ошибку при каждом
вызове;and.callThrough() — вызывает оригинальную функцию
(актуально для метода объекта, но не standalone spy).Методы calls.argsFor(index) и
calls.allArgs() позволяют более детально исследовать
вызовы:
const spy = jasmine.createSpy('spy');
spy(10, 20);
spy(30, 40);
console.log(spy.calls.argsFor(0)); // [10, 20]
console.log(spy.calls.allArgs()); // [[10, 20], [30, 40]]
Также можно проверить контекст вызова с помощью
calls.all() и calls.mostRecent():
const spy = jasmine.createSpy('spy');
const obj = { method: spy };
obj.method(5);
console.log(spy.calls.mostRecent().object === obj); // true
Standalone spies идеально подходят для тестирования callback-функций и асинхронного кода:
function fetchData(callback) {
setTimeout(() => callback('data'), 100);
}
const callbackSpy = jasmine.createSpy('callbackSpy');
fetchData(callbackSpy);
setTimeout(() => {
expect(callbackSpy).toHaveBeenCalledWith('data');
}, 150);
Для промисов можно комбинировать spies с
async/await:
const asyncSpy = jasmine.createSpy('asyncSpy').and.callFake(async () => 'ok');
async function test() {
const result = await asyncSpy();
expect(result).toBe('ok');
expect(asyncSpy).toHaveBeenCalled();
}
test();
beforeEach и очистка spyЧасто spy создаётся в beforeEach, чтобы каждый тест
начинался с чистого состояния:
let mySpy;
beforeEach(() => {
mySpy = jasmine.createSpy('mySpy');
});
it('должен вызываться один раз', () => {
mySpy();
expect(mySpy.calls.count()).toBe(1);
});
Это предотвращает накопление данных о вызовах между тестами и обеспечивает независимость каждого кейса.
Standalone spies через createSpy предоставляют
универсальный способ отслеживания вызовов функций, проверки аргументов,
настройки возвращаемых значений и подмены поведения. Они эффективны для
тестирования callback-ов, промисов, независимых модулей и любых функций,
не интегрированных в объект. Комбинируя методы and.* и
calls.*, можно создавать детальные и точные проверки
поведения кода, что делает Jasmine гибким инструментом для
юнит-тестирования.