В Jasmine существует мощный механизм шпионов
(spies), позволяющий отслеживать вызовы функций и управлять их
поведением. Одним из ключевых инструментов управления результатами
вызова функции является метод and.returnValue. Он позволяет
задать фиксированное значение, которое будет возвращаться при каждом
вызове шпионской функции.
and.returnValueМетод применяется к шпиону следующим образом:
const calculator = {
sum: (a, b) => a + b
};
spyOn(calculator, 'sum').and.returnValue(10);
const result = calculator.sum(3, 7);
console.log(result); // 10
В этом примере исходная реализация sum полностью
игнорируется. Каждый вызов calculator.sum будет возвращать
10, независимо от переданных аргументов. Это
позволяет:
callFakeand.returnValue возвращает фиксированное
значение, тогда как and.callFake позволяет
подменять функцию с произвольной логикой. Например:
spyOn(calculator, 'sum').and.callFake((a, b) => a * b);
console.log(calculator.sum(3, 4)); // 12
Если требуется лишь стабилизировать возвращаемое значение без
написания новой логики, and.returnValue является более
лаконичным и наглядным решением.
and.returnValue работает только с синхронными
значениями. Для имитации промисов или асинхронных результатов
используется and.returnValue(Promise.resolve(value)):
const api = {
fetchData: () => fetch('/data')
};
spyOn(api, 'fetchData').and.returnValue(Promise.resolve({ id: 1, name: 'Test' }));
api.fetchData().then(data => console.log(data)); // { id: 1, name: 'Test' }
Это позволяет полностью контролировать поведение асинхронных функций без необходимости обращаться к реальному серверу.
Метод and.returnValue не учитывает аргументы вызова.
Любое количество вызовов с любыми параметрами вернёт одно и то же
значение. Если требуется возвращать разные значения в зависимости от
аргументов, нужно использовать:
and.callFake с кастомной логикойand.returnValues для последовательных значенийПример с and.returnValues:
spyOn(calculator, 'sum').and.returnValues(1, 2, 3);
console.log(calculator.sum()); // 1
console.log(calculator.sum()); // 2
console.log(calculator.sum()); // 3
console.log(calculator.sum()); // undefined (после исчерпания списка)
and.returnValueМетод and.returnValue хорошо сочетается с проверками
вызова через toHaveBeenCalled и
toHaveBeenCalledWith:
spyOn(calculator, 'sum').and.returnValue(5);
calculator.sum(2, 3);
expect(calculator.sum).toHaveBeenCalled();
expect(calculator.sum).toHaveBeenCalledWith(2, 3);
expect(calculator.sum()).toBe(5);
Это позволяет не только гарантировать возвращаемое значение, но и отслеживать корректность использования функции в тестируемом коде.
and.returnValue нельзя использовать для
конструкторов или методов, которые должны создавать
новые объекты с внутренним состоянием, так как возвращаемое значение
будет одно и то же для всех вызовов.callFake.and.returnValues.Предположим, есть модуль, который зависит от внешнего сервиса:
const weatherService = {
getTemperature: city => {
// Реальный вызов к API
}
};
const weatherReporter = {
report: city => `Температура в ${city} ${weatherService.getTemperature(city)}°C`
};
Тест с подменой значения:
spyOn(weatherService, 'getTemperature').and.returnValue(25);
expect(weatherReporter.report('Москва')).toBe('Температура в Москва 25°C');
expect(weatherService.getTemperature).toHaveBeenCalledWith('Москва');
Здесь тест полностью изолирован от внешнего API, а результат фиксирован, что делает проверку предсказуемой.
Метод and.returnValue — это простой и
эффективный инструмент для управления возвращаемыми значениями
шпионских функций. Он позволяет создавать стабильные, изолированные
тесты и минимизировать зависимости, сохраняя при этом ясность кода.
Используется преимущественно для синхронных функций с фиксированным
результатом, но может быть адаптирован для работы с промисами и
последовательными значениями.