Функция jest.fn()

Функция jest.fn() в библиотеке Jest используется для создания мок-объектов и подстановок в тестах. Это позволяет отслеживать вызовы функций, их аргументы и возвращаемые значения, а также контролировать поведение функций, чтобы тесты оставались изолированными и не зависели от внешних факторов.

Основное использование

При создании мок-функции с помощью jest.fn() можно легко симулировать поведение реальной функции, контролировать ее вызовы и результат. Например, если в тестируемом коде есть вызов функции, а нам нужно проверить, как она была вызвана, или подменить её результат, можно использовать jest.fn().

Пример:

const mockFunction = jest.fn();
mockFunction('test', 42);

expect(mockFunction).toHaveBeenCalledWith('test', 42);

В этом примере создается мок-функция mockFunction, которая вызывается с двумя аргументами: 'test' и 42. После этого проверяется, что функция была вызвана именно с этими аргументами с помощью метода toHaveBeenCalledWith().

Моки с возвращаемыми значениями

С помощью jest.fn() можно также задать возвращаемое значение для мок-функции. Это удобно, когда требуется замокать функцию, которая взаимодействует с внешними сервисами или возвращает данные, которые трудно или неудобно получать в процессе тестирования.

Пример:

const mockFunction = jest.fn().mockReturnValue(42);

const result = mockFunction();
expect(result).toBe(42);

Здесь функция всегда будет возвращать значение 42, независимо от того, что ей передают в качестве аргументов.

Моки с различными значениями

Если требуется, чтобы функция возвращала разные значения в зависимости от вызова, можно использовать метод mockReturnValueOnce(). Это позволяет задать цепочку возвращаемых значений, что полезно в случае, если тестируемая функция изменяет своё поведение при каждом вызове.

Пример:

const mockFunction = jest.fn()
  .mockReturnValueOnce(1)
  .mockReturnValueOnce(2)
  .mockReturnValueOnce(3);

expect(mockFunction()).toBe(1);
expect(mockFunction()).toBe(2);
expect(mockFunction()).toBe(3);

Здесь каждый вызов функции mockFunction() возвращает разное значение в зависимости от порядка вызовов.

Моки с асинхронными значениями

Для работы с асинхронными функциями также существует поддержка моков. С помощью метода mockResolvedValue() можно задавать возвращаемые значения для промисов. В случае с отклонением промиса используется метод mockRejectedValue().

Пример:

const mockAsyncFunction = jest.fn().mockResolvedValue('success');

mockAsyncFunction().then(result => {
  expect(result).toBe('success');
});

В этом примере mockAsyncFunction возвращает промис, который разрешается значением 'success'.

Подсчёт вызовов и аргументов

Мок-функции, созданные с помощью jest.fn(), позволяют отслеживать количество вызовов, переданные аргументы и возвращаемые значения. Для этого Jest предоставляет несколько полезных методов.

  • toHaveBeenCalled() — проверяет, был ли вызван мок.
  • toHaveBeenCalledTimes() — проверяет, сколько раз был вызван мок.
  • toHaveBeenCalledWith() — проверяет, были ли переданы в мок конкретные аргументы.
  • toHaveReturned() — проверяет, было ли возвращено какое-либо значение.

Пример:

const mockFunction = jest.fn();

mockFunction('first call');
mockFunction('second call');

expect(mockFunction).toHaveBeenCalledTimes(2);
expect(mockFunction).toHaveBeenCalledWith('first call');

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

Моки и реализации функций

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

Пример:

const mockImplementation = jest.fn((x, y) => x + y);

expect(mockImplementation(2, 3)).toBe(5);

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

Слежение за вызовами и результаты

Одним из полезных аспектов работы с jest.fn() является возможность получения информации о том, как именно был вызван мок. Например, можно получить доступ к списку аргументов, с которыми был вызван мок, или результатам всех вызовов.

Пример:

const mockFunction = jest.fn().mockImplementation((x, y) => x + y);

mockFunction(2, 3);
mockFunction(4, 5);

console.log(mockFunction.mock.calls); // [['2', '3'], ['4', '5']]
console.log(mockFunction.mock.results); // [{ type: 'return', value: 5 }, { type: 'return', value: 9 }]

Здесь с помощью свойств mock.calls и mock.results можно получить информацию о том, какие аргументы были переданы в функцию, а также о результатах её выполнения.

Полезные методы для работы с моками

  1. mockClear() — очищает информацию о вызовах функции, но не сбрасывает её реализацию.
  2. mockReset() — сбрасывает все вызовы и информацию о моках, но сохраняет саму реализацию.
  3. mockRestore() — восстанавливает исходное поведение функции, если она была подменена мок-функцией.

Пример:

const mockFunction = jest.fn().mockReturnValue('value');

mockFunction();
mockFunction();
mockFunction.mockClear();

console.log(mockFunction.mock.calls.length); // 0, после очистки

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

Использование с объектами и методами

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

Пример:

const object = {
  method: jest.fn().mockReturnValue('test result'),
};

expect(object.method()).toBe('test result');

Здесь method объекта object подменяется на мок-функцию, которая возвращает строку 'test result'.

Итог

Использование jest.fn() предоставляет мощные инструменты для тестирования с мокаемыми функциями. Это позволяет разработчикам создавать изолированные тесты, контролировать поведение зависимостей и отслеживать важные параметры, такие как количество вызовов, переданные аргументы и возвращаемые значения.