/
Вопросы и ответы
/
JavaScript
/

В чём разница jest.fn и jest.spyOn

В чём разница jest.fn и jest.spyOn

При решении задачи тесты проходят как при создании mock через jest.fn, так и через jest.spyOn. Если результат одинаков, то в чем разница между этими командами?

3 года назад

Ivan Gagarinov

Ответы

6

Они действительно похожи, но есть различия.

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;

3 года назад

Ivan Gagarinov

0

Добрый день! Почему то на этой строчке const addMock = jest.spyOn(math, 'add'); падает с ошибкой:

TypeError: Cannot assign to read only property 'add' of object '[object Module]'

3 года назад

Pavel Biryukov