В тестировании на JavaScript spies представляют собой
инструмент для наблюдения за функциями без изменения их исходной логики.
Они позволяют отслеживать вызовы функций, аргументы, с которыми функции
были вызваны, количество вызовов, а также управлять поведением функций в
тестовой среде. Spies особенно полезны для тестирования
взаимодействий между объектами и модульных тестов, где необходимо
изолировать зависимые компоненты.
spyJasmine предоставляет несколько способов создания spy.
Основные из них:
spyOnconst calculator = {
add(a, b) {
return a + b;
}
};
spyOn(calculator, 'add');
calculator.add(2, 3);
expect(calculator.add).toHaveBeenCalled();
expect(calculator.add).toHaveBeenCalledWith(2, 3);
spyOn заменяет указанную функцию шпионским аналогом,
позволяя отслеживать её вызовы. Фактический результат функции по
умолчанию не изменяется, если не указано иное.
jasmine.createSpyconst spyFunction = jasmine.createSpy('mySpy');
spyFunction('test');
expect(spyFunction).toHaveBeenCalled();
expect(spyFunction).toHaveBeenCalledWith('test');
createSpy создаёт полностью автономный шпион, который не
связан с конкретным объектом. Используется для замены функций, которые
ещё не реализованы или зависят от внешних сервисов.
jasmine.createSpyObjconst serviceSpy = jasmine.createSpyObj('Service', ['getData', 'setData']);
serviceSpy.getData();
expect(serviceSpy.getData).toHaveBeenCalled();
createSpyObj создаёт объект с набором шпионов, что
удобно для имитации сложных сервисов или модулей с множественными
методами.
spiesПо умолчанию шпион только отслеживает вызовы функции. Для имитации поведения функции используются специальные методы:
and.callThrough() – вызывает
оригинальную функцию. Полезно, когда требуется сохранить её исходное
поведение.spyOn(calculator, 'add').and.callThrough();
expect(calculator.add(1, 2)).toBe(3);
and.returnValue(value) – возвращает
заданное значение при каждом вызове.spyOn(calculator, 'add').and.returnValue(10);
expect(calculator.add(1, 2)).toBe(10);
and.callFake(fn) – заменяет функцию на
пользовательскую реализацию.spyOn(calculator, 'add').and.callFake((a, b) => a * b);
expect(calculator.add(2, 3)).toBe(6);
and.throwError(message) – вызывает
ошибку при вызове функции.spyOn(calculator, 'add').and.throwError('Ошибка!');
expect(() => calculator.add(1, 2)).toThrowError('Ошибка!');
spiesJasmine предоставляет набор матчеров для проверки вызовов шпионов:
toHaveBeenCalled() – проверяет, что
функция была вызвана хотя бы один раз.toHaveBeenCalledTimes(number) –
проверяет точное количество вызовов.toHaveBeenCalledWith(...args) –
проверяет, что функция была вызвана с указанными аргументами.toHaveBeenCalledOnceWith(...args) –
проверяет однократный вызов с конкретными аргументами.toHaveBeenCalledBefore(spy) –
проверяет порядок вызовов между шпионами.toHaveBeenCalledAfter(spy) –
аналогично, но для проверки вызова после другого шпиона.Пример комплексной проверки:
spyOn(calculator, 'add');
spyOn(calculator, 'subtract');
calculator.add(5, 3);
calculator.subtract(2, 1);
expect(calculator.add).toHaveBeenCalledBefore(calculator.subtract);
expect(calculator.subtract).toHaveBeenCalledWith(2, 1);
expect(calculator.add).toHaveBeenCalledTimes(1);
spies для изоляции зависимостейВ модульном тестировании важно изолировать тестируемый код от внешних
зависимостей. Spies позволяют:
Пример имитации API-сервиса:
const apiService = {
fetchData() {
// Реальный HTTP-запрос
}
};
spyOn(apiService, 'fetchData').and.returnValue(Promise.resolve({ data: 'test' }));
myFunctionUsingAPI(apiService).then(result => {
expect(result).toBe('test');
});
spiesspyOn только для существующих методов
объектов. Для несуществующих методов — createSpy или
createSpyObj.callThrough сохраняется оригинальная
логика функции, что полезно для интеграционных тестов.afterEach(() => {
jasmine.restoreAllSpies();
});
callFake и returnValue для
моделирования сложных сценариев без фактического выполнения
зависимостей.Spies в Jasmine обеспечивают мощный механизм контроля
функций и методов, позволяя полностью управлять их поведением и
проверять взаимодействие компонентов на всех уровнях тестирования. Они
являются ключевым инструментом для создания надёжных, изолированных и
предсказуемых тестов в JavaScript.