Отслеживание вызовов моков

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

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

Моки в Jest

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

Пример создания мока:
const myMock = jest.fn();

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

Отслеживание вызовов мок-функций

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

Проверка количества вызовов

Для того чтобы проверить, сколько раз была вызвана мок-функция, используется метод mock.calls. Этот метод возвращает массив всех вызовов, сделанных для данной функции.

Пример:

const myMock = jest.fn();

myMock();
myMock();

console.log(myMock.mock.calls.length);  // Выведет: 2

Здесь mock.calls.length указывает на количество вызовов мок-функции.

Проверка аргументов, с которыми была вызвана мок-функция

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

Пример:

const myMock = jest.fn();

myMock(1, 'a');
myMock(2, 'b');

console.log(myMock.mock.calls[0]);  // Выведет: [1, 'a']
console.log(myMock.mock.calls[1]);  // Выведет: [2, 'b']

Каждый элемент mock.calls — это массив аргументов, переданных при соответствующем вызове.

Проверка значения, которое вернула мок-функция

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

  • type — тип результата (например, return, throw, если функция выбрасывает исключение).
  • value — значение, возвращаемое мок-функцией.

Пример:

const myMock = jest.fn()
  .mockReturnValueOnce(10)
  .mockReturnValueOnce(20);

myMock();
myMock();

console.log(myMock.mock.results[0].value);  // Выведет: 10
console.log(myMock.mock.results[1].value);  // Выведет: 20

Ожидания и проверки на моках

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

Проверка количества вызовов

Для проверки того, сколько раз была вызвана мок-функция, можно использовать метод .toHaveBeenCalledTimes().

Пример:

const myMock = jest.fn();

myMock();
myMock();

expect(myMock).toHaveBeenCalledTimes(2);
Проверка на конкретные аргументы

Если необходимо удостовериться, что мок-функция была вызвана с конкретными аргументами, используется метод .toHaveBeenCalledWith().

Пример:

const myMock = jest.fn();

myMock(1, 'a');
myMock(2, 'b');

expect(myMock).toHaveBeenCalledWith(1, 'a');
expect(myMock).toHaveBeenCalledWith(2, 'b');

Моки с различным поведением

Можно настроить мок-функции так, чтобы они возвращали различные значения в зависимости от вызова, с помощью методов .mockReturnValueOnce() и .mockResolvedValueOnce().

Пример использования:
const myMock = jest.fn()
  .mockReturnValueOnce(10)
  .mockReturnValueOnce(20);

console.log(myMock());  // Выведет: 10
console.log(myMock());  // Выведет: 20
console.log(myMock());  // Выведет: undefined (по умолчанию)

Каждое использование .mockReturnValueOnce() изменяет поведение функции только для одного вызова.

Асинхронные моки

Для асинхронных функций Jest также предоставляет возможность мокировать возвращаемые промисы через метод .mockResolvedValueOnce().

Пример:

const myAsyncMock = jest.fn()
  .mockResolvedValueOnce('Success')
  .mockResolvedValueOnce('Failure');

myAsyncMock().then(res => console.log(res));  // Выведет: 'Success'
myAsyncMock().then(res => console.log(res));  // Выведет: 'Failure'

Моки с поведением по умолчанию

Моки могут иметь поведение по умолчанию, которое применимо к каждому вызову. Это можно настроить с помощью метода .mockReturnValue().

Пример:

const myMock = jest.fn().mockReturnValue('default value');

console.log(myMock());  // Выведет: 'default value'
myMock.mockReturnValueOnce('specific value');
console.log(myMock());  // Выведет: 'specific value'
console.log(myMock());  // Выведет: 'default value'

Резюме

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