В тестировании JavaScript с использованием Jasmine одной из ключевых возможностей является наблюдение за вызовами функций и подмена их поведения без изменения исходного кода. Для этого применяется встроенный механизм spy.
spyOn — это метод Jasmine, который позволяет
шпионить за существующими методами объектов. Он
предоставляет полный контроль над вызовами функции, позволяет проверять
параметры, количество вызовов и подменять реализацию.
spyOnspyOn(object, 'methodName');
object — объект, содержащий метод, который нужно
«шпионить».methodName — строка с именем метода объекта.После применения spyOn, оригинальная функция заменяется
специальной «шпионской» функцией, которая сохраняет информацию о
вызовах.
Пример:
const 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 отслеживает вызов метода
add и его аргументы. Оригинальный результат функции
по умолчанию не выполняется, если не указана реализация через
методы spy.
spyOn позволяет изменять поведение
функции, чтобы тестирование не зависело от оригинальной
реализации.
and.callThrough() — сохраняет
оригинальное поведение функции, одновременно позволяя отслеживать
вызовы:spyOn(calculator, 'add').and.callThrough();
const result = calculator.add(2, 3);
expect(result).toBe(5);
expect(calculator.add).toHaveBeenCalled();
and.returnValue(value) — всегда
возвращает указанное значение:spyOn(calculator, 'add').and.returnValue(10);
const result = calculator.add(2, 3);
expect(result).toBe(10);
and.callFake(fakeFunction) — заменяет
функцию своей реализацией:spyOn(calculator, 'add').and.callFake((a, b) => a * b);
expect(calculator.add(2, 3)).toBe(6);
and.stub() — создает пустую функцию,
которая ничего не делает и возвращает undefined.
Используется для подавления побочных эффектов:spyOn(calculator, 'add').and.stub();
expect(calculator.add(2, 3)).toBeUndefined();
Jasmine предоставляет набор удобных матчеров для spy:
toHaveBeenCalled() — проверяет, был ли
вызов функции.toHaveBeenCalledTimes(number) —
проверяет количество вызовов.toHaveBeenCalledWith(...args) —
проверяет, вызывалась ли функция с указанными аргументами.toHaveBeenCalledOnceWith(...args) —
проверяет, что функция вызвалась один раз с указанными аргументами.toHaveBeenCalledBefore(spy) /
toHaveBeenCalledAfter(spy) — проверяет порядок
вызовов между spy.Пример проверки нескольких вызовов:
calculator.add(1, 2);
calculator.add(3, 4);
expect(calculator.add).toHaveBeenCalledTimes(2);
expect(calculator.add).toHaveBeenCalledWith(3, 4);
spyOn поддерживает асинхронные функции и промисы. Для
работы с async/await или функциями, возвращающими промис,
можно использовать and.callFake:
const api = {
fetchData() {
return fetch('/data');
}
};
spyOn(api, 'fetchData').and.callFake(() => Promise.resolve({ data: 123 }));
await api.fetchData().then(result => {
expect(result.data).toBe(123);
});
Это позволяет тестировать код без реальных сетевых запросов.
spyOnspyOn на переменные, функции вне
объектов или свойства, не являющиеся функцией.spyOn(Class.prototype, 'method').Пример для классов:
class User {
greet(name) {
return `Hello, ${name}!`;
}
}
spyOn(User.prototype, 'greet');
const user = new User();
user.greet('Alice');
expect(user.greet).toHaveBeenCalledWith('Alice');
spyOn для разделения теста и
зависимости. Например, чтобы не вызывать сетевые запросы или
изменения базы данных.and.callThrough() только когда нужно
протестировать и вызов, и результат функции.afterEach(() => {
jasmine.restoreAllSpies();
});
spyOn — это универсальный инструмент для
мониторинга, контроля и подмены поведения функций,
обеспечивающий детализированное тестирование JavaScript-приложений без
изменения исходного кода. Правильное применение spy позволяет создавать
надежные и изолированные тесты, полностью контролируя вызовы и их
результаты.