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

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

Аватар пользователя Ivan Gagarinov
Ivan Gagarinov
16 августа 2022

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

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;
5 0
Аватар пользователя Pavel Biryukov
Pavel Biryukov
26 декабря 2022

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

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

Есть что добавить? Зарегистрируйтесь

или войдите в аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Курсы по программированию в Хекслете

Программирование

Веб-разработка

Разработка, верстка и деплой сайтов и веб-приложений, трудоустройство для разработчиков

Frontend-разработка

Разработка внешнего интерфейса сайтов и веб-приложений и верстка

Создание сайтов

Разработка сайтов и веб-приложений на JS, Python, Java, PHP и Ruby on Rails

Backend-разработка

Разработка серверной части сайтов и веб-приложений

Тестирование

Ручное тестирование и автоматизированное тестирование на JS, Python, Java и PHP

Аналитика данных

Сбор, анализ и интерпретация данных на Python

Интенсивные курсы

Интенсивное обучение для продолжающих

DevOps

Автоматизация настройки локального окружения и серверов, развертывания и деплоя

Математика для программистов

Обучение разделам математики, которые будут полезны при изучении программирования

Тест-драйв

JavaScript

Разработка сайтов и веб-приложений и автоматизированное тестирование на JS

Python

Веб-разработка, автоматическое тестирование и аналитика данных на Python

Java

Веб-разработка и автоматическое тестирование на Java

PHP

Веб-разработка и автоматическое тестирование на PHP

Ruby

Разработка сайтов и веб-приложений на Ruby on Rails

Go

Курсы по веб-разработке на языке Go

HTML

Современная верстка с помощью HTML и CSS

SQL

Проектирование базы данных, выполнение SQL-запросов и изучение реляционных СУБД

Git

Система управления версиями Git, регулярные выражения и основы командой строки

Бесплатные курсы

Бесплатные курсы по тестированию, дата-аналитике, верстке, программированию на Python, Java, PHP и JavaScript.