Понимание Jest Mocks

Мокинг - это метод изоляции испытуемых путем замены зависимостей объектами, которые вы можете контролировать и проверять. Зависимостью может быть все, от чего зависит ваш субъект, но обычно это модуль, который субъект импортирует.

Для JavaScript доступны отличные библиотеки имитации, такие как testdouble и sinon, а Jest предоставляет имитацию прямо из коробки.

Недавно я присоединился к Jest в качестве соавтора, чтобы помочь в сортировке системы отслеживания проблем, и я заметил много вопросов о том, как работает насмешка в Jest, поэтому я подумал, что смогу составить руководство, объясняющее это.

Когда мы говорим о насмешке в Jest, мы обычно говорим о замене зависимостей имитационной функцией. В этой статье мы рассмотрим фиктивную функцию, а затем рассмотрим различные способы замены ею зависимостей.

Мок-функция

Цель издевательства - заменить то, что мы не контролируем, тем, что делаем мы, поэтому важно, чтобы то, чем мы это заменяем, имело все необходимые функции.

Функция Mock предоставляет следующие возможности:

  • Захват звонков
  • Установить возвращаемые значения
  • Изменить реализацию

Самый простой способ создать экземпляр Mock Function - использовать jest.fn().

С помощью этого и Jest Expect легко протестировать захваченные вызовы:

и мы можем изменить возвращаемое значение, реализацию или разрешение обещания:

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

Внедрение зависимости

Один из распространенных способов использования фиктивной функции - передача ее непосредственно в качестве аргумента функции, которую вы тестируете. Это позволяет вам запустить своего тестового объекта, а затем подтвердить, как был вызван макет и с какими аргументами:

Это надежная стратегия, но она требует, чтобы ваш код поддерживал внедрение зависимостей. Часто это не так, поэтому вместо этого нам понадобятся инструменты для имитации существующих модулей и функций.

Модули и функции модуля

В Jest есть три основных типа имитации модулей и функций:

  • jest.fn: имитируйте функцию
  • jest.mock: Имитация модуля
  • jest.spyOn: Шпионить за функцией или издеваться над ней

Каждый из них каким-то образом создает фиктивную функцию. Чтобы объяснить, как каждый из них это делает, рассмотрим эту структуру проекта:

В этой настройке обычно проверяют app.js и хотят либо не вызывать фактические math.js функции, либо шпионить за ними, чтобы убедиться, что они вызываются должным образом. Этот пример банален, но представьте, что math.js является сложным вычислением или требует некоторого ввода-вывода, которого вы хотите избежать:

Имитация функции с помощью jest.fn

Самая основная стратегия имитации - переназначить функцию фиктивной функции. Затем, где бы ни использовались переназначенные функции, вместо исходной функции будет вызываться макет:

Этот тип издевательства менее распространен по двум причинам:

  • jest.mock делает это автоматически для всех функций в модуле
  • jest.spyOn делает то же самое, но позволяет восстановить исходную функцию.

Смоделируйте модуль с помощью jest.mock

Более распространенным подходом является использование jest.mock для автоматической установки всех экспортов модуля в фиктивную функцию. Итак, вызов jest.mock('./math.js'); по существу устанавливает math.js в:

Отсюда мы можем использовать любую из вышеперечисленных функций макетной функции для всех экспортов модуля:

Это самая простая и распространенная форма насмешки (и это тот тип насмешки, который Jest делает для вас с automock: true).

Единственным недостатком этой стратегии является то, что трудно получить доступ к исходной реализации модуля. В таких случаях можно использовать spyOn.

Шпионьте или имитируйте функцию с помощью jest.spyOn

Иногда вы хотите только наблюдать, как вызывается метод, но сохраните исходную реализацию. В других случаях вы можете поиздеваться над реализацией, но позже восстановить оригинал в пакете.

В этих случаях вы можете использовать jest.spyOn.

Здесь мы просто «шпионим» за вызовами математической функции, но оставляем исходную реализацию на месте:

Это полезно в ряде сценариев, когда вы хотите утверждать, что определенные побочные эффекты происходят, не заменяя их.

В других случаях вы можете имитировать функцию, но затем восстановить исходную реализацию:

Это полезно для тестов в одном файле, но не обязательно в ловушке afterAll, поскольку каждый тестовый файл в Jest изолирован.

Главное, что нужно помнить о jest.spyOn, это то, что это просто сахар для базового jest.fn() использования. Мы можем достичь той же цели, сохранив исходную реализацию, установив фиктивную реализацию на оригинал и переназначив оригинал позже:

Фактически, именно так jest.spyOn реализовано.

Заключение

В этой статье мы узнали о фиктивной функции и различных стратегиях переназначения модулей и функций для отслеживания вызовов, замены реализаций и установки возвращаемых значений.

Я надеюсь, что это помогло упростить ваше понимание имитаторов Jest, чтобы вы могли безболезненно тратить больше времени на написание тестов. Для получения дополнительной информации и рекомендаций по издевательству ознакомьтесь с этим 700+ слайд-докладом Джастина Сирлса под названием Не смейтесь надо мной.

По любым вопросам обращайтесь ко мне в twitter, Stack Overflow или на наш канал Discord!