Мок-функции: jest.fn()

Урок знакомит с мок-функциями: как создать заглушку и проверить, как её вызывали.

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

Зачем мок-функции

Иногда важно не то, что функция возвращает, а то, как её вызвали: сколько раз, с какими аргументами. Например, обработчик события должен вызвать колбэк ровно один раз. Мок-функция всё это запоминает.

Создание и проверки

const callback = jest.fn();

[1, 2, 3].forEach(callback);

expect(callback).toHaveBeenCalled();          // вызывалась
expect(callback).toHaveBeenCalledTimes(3);     // ровно 3 раза
expect(callback).toHaveBeenCalledWith(2, 1);   // forEach передаёт (элемент, индекс)

Задание поведения

Мок-функции можно научить возвращать значение:

const getPrice = jest.fn();
getPrice.mockReturnValue(100);
getPrice.mockReturnValueOnce(50); // первый вызов

expect(getPrice()).toBe(50);  // once
expect(getPrice()).toBe(100); // дальше — обычное значение

const fetchData = jest.fn().mockResolvedValue({ ok: true }); // для async

Идея «шпионящей» функции на чистом JS

Соберём мини-версию jest.fn(), чтобы понять механику записи вызовов:

function createMock(returnValue) {
  function mock(...args) {
    mock.calls.push(args);
    return returnValue;
  }
  mock.calls = [];
  return mock;
}

const onClick = createMock('ok');

onClick('button', 1);
onClick('link', 2);

console.log('вызвана раз:', onClick.calls.length);
console.log('аргументы 1-го вызова:', JSON.stringify(onClick.calls[0]));
console.log('возврат:', onClick('x'));

Вывод:

вызвана раз: 2
аргументы 1-го вызова: ["button",1]
возврат: ok

Настоящий jest.fn() хранит вызовы в mock.calls точно так же — а матчеры вроде toHaveBeenCalledWith просто заглядывают в этот массив.

Доступ к записанным вызовам

У мока есть свойство .mock:

const fn = jest.fn();
fn('a');
fn('b');

console.log(fn.mock.calls);     // [['a'], ['b']]
console.log(fn.mock.calls[0]);  // ['a'] — аргументы первого вызова

Итог

  • jest.fn() создаёт мок-функцию, запоминающую все вызовы.
  • Проверки: toHaveBeenCalled, toHaveBeenCalledTimes, toHaveBeenCalledWith.
  • Поведение задают mockReturnValue, mockReturnValueOnce, mockResolvedValue.
  • Все вызовы доступны в fn.mock.calls.
Проверьте себя
1. Что главным образом запоминает jest.fn()?
AТолько возвращаемое значение
BВсе свои вызовы и переданные аргументы
CИсходный код функции
DВремя выполнения
2. Какой матчер проверяет, что мок вызвали с конкретными аргументами?
AtoBeCalledMaybe
BtoHaveBeenCalledWith
CtoReturn
DtoContain
3. Что делает mockReturnValueOnce(50) у мок-функции?
AДелает функцию всегда возвращающей 50
BЗадаёт значение 50 только для следующего вызова
CВызывает функцию 50 раз
DСбрасывает все вызовы
Поддержать проект