В чём разница jest.fn и jest.spyOn
При решении задачи тесты проходят как при создании mock через jest.fn, так и через jest.spyOn. Если результат одинаков, то в чем разница между этими командами?
Они действительно похожи, но есть различия.
jest.fn()
создан чтобы полностью подменять на свою реализацию (мокинг), то есть если вы, например, не хотите, чтобы вызывались какие-то реальные запросы в базу данных при тестировании или какие-то другие побочные эффекты.
jest.spyOn()
же позволяет просто отслеживать что функция была вызвана, без подмены реализации этой функции. jest.spyOn()
так же умеет и подменять реализацию (как и jest.fn()
), но он умеет это делать на время. То есть, если вы хотите сохранить оригинальную реализацию функции и может быть вызывать её при каких-то сценариях, тот тут понадобится jest.spyOn()
.
На самом деле jest.spyOn()
- это просто синтаксический сахар. То же самое мы можем сделать используя базовый метод jest.fn()
. Для этого нужно сохранять базовую реализацию и подменять её обратно, когда это нужно:
import app from './app';
import math from './math';
test('test add', () => {
// сохраняем базовую реализацию
const original = math.add;
const addMock = jest.spyOn(math, 'add');
// подменяем реализацию
math.add = jest.fn(originalAdd);
math.add.mockImplementation(() => 'mock');
expect(app.doAdd(1, 2)).toEqual('mock');
expect(math.add).toHaveBeenCalledWith(1, 2);
// восстанавливаем реализацию на оригинальную
math.add = original;
expect(app.doAdd(1, 2)).toEqual(3);
});
Возможные проблемы
Ошибка вида
TypeError: Cannot assign to read only property 'add' of object '[object Module]'
связана с особенностью экспорта из модуля, из которого отслеживается функция. Например, такой экспорт будет работать для примеров выше:
const math {
add(a, b) {
return a + b;
},
};
export default math;
Добрый день!
Почему то на этой строчке const addMock = jest.spyOn(math, 'add');
падает с ошибкой:
TypeError: Cannot assign to read only property 'add' of object '[object Module]'