В Jasmine отслеживание вызовов функций реализуется через шпионы (spies). Шпион — это объект, который перехватывает вызовы функции, записывает параметры, с которыми она была вызвана, количество вызовов, а при необходимости позволяет контролировать возвращаемые значения или поведение функции.
Существует несколько способов создания шпионов:
const calculator = {
add: (a, b) => a + b
};
spyOn(calculator, 'add');
calculator.add(2, 3);
expect(calculator.add).toHaveBeenCalled();
expect(calculator.add).toHaveBeenCalledWith(2, 3);
const callback = jasmine.createSpy('callback');
callback('test');
expect(callback).toHaveBeenCalled();
expect(callback).toHaveBeenCalledWith('test');
const fetchData = jasmine.createSpy('fetchData').and.returnValue(Promise.resolve('data'));
fetchData().then(result => {
expect(result).toBe('data');
});
Также доступны методы and.callFake для определения
собственной функции и and.throwError для имитации
ошибок.
Jasmine предоставляет мощный API для анализа шпионов:
Пример:
const logger = jasmine.createSpy('logger');
logger('start');
logger('process');
logger('end');
expect(logger).toHaveBeenCalledTimes(3);
expect(logger.calls.all()[1].args).toEqual(['process']);
Каждый шпион содержит объект calls, который
предоставляет детальную статистику:
true, если
шпион вызывался хотя бы один раз.this.Пример использования calls:
const math = jasmine.createSpyObj('math', ['multiply']);
math.multiply(2, 3);
math.multiply(4, 5);
expect(math.multiply.calls.count()).toBe(2);
expect(math.multiply.calls.argsFor(0)).toEqual([2, 3]);
math.multiply.calls.reset();
expect(math.multiply.calls.any()).toBeFalse();
Jasmine позволяет создавать шпионы на все методы объекта одновременно:
const api = {
getUser: () => {},
saveUser: () => {}
};
const apiSpy = jasmine.createSpyObj('api', ['getUser', 'saveUser']);
apiSpy.getUser('Alice');
expect(apiSpy.getUser).toHaveBeenCalledWith('Alice');
Для каждого метода можно отдельно определить возвращаемое значение:
apiSpy.getUser.and.returnValue({ name: 'Alice' });
expect(apiSpy.getUser()).toEqual({ name: 'Alice' });
Шпион может:
and.callThrough()and.returnValue(value)and.callFake(fn)and.throwError(message)Пример использования callThrough:
const calculator = {
multiply: (a, b) => a * b
};
spyOn(calculator, 'multiply').and.callThrough();
expect(calculator.multiply(2, 3)).toBe(6);
expect(calculator.multiply).toHaveBeenCalledWith(2, 3);
Jasmine позволяет контролировать порядок вызовов функций, используя массив объектов вызовов:
const a = jasmine.createSpy('a');
const b = jasmine.createSpy('b');
a();
b();
expect(a.calls.first().invocationOrder).toBeLessThan(b.calls.first().invocationOrder);
Это полезно для тестирования сложных процессов, где важен порядок операций.
spyOn для методов объектов, чтобы
сохранить возможность контроля оригинальной реализации.createSpy для независимых функций обратного
вызова.calls.reset()), если шпион используется повторно.toHaveBeenCalledWith(jasmine.objectContaining({...})) для
частичной проверки объекта.Отслеживание вызовов функций с помощью шпионов Jasmine обеспечивает точный контроль за поведением кода и позволяет создавать надежные и детальные юнит-тесты, фиксируя не только результат, но и всю динамику вызовов функций.