Шпионы с jest.spyOn()

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

Основы использования jest.spyOn()

Функция jest.spyOn() создает шпион на метод объекта. Он принимает два аргумента:

  1. Объект — объект, на котором будет вызван шпион.
  2. Имя метода — строка, указывающая на метод, который нужно отслеживать.

Пример:

const user = {
  getName() {
    return 'John Doe';
  }
};

const spy = jest.spyOn(user, 'getName');

В этом примере создается шпион для метода getName() объекта user. После этого можно отслеживать, сколько раз метод был вызван, какие аргументы были переданы, и какие результаты были получены.

Просмотр вызовов метода

После того как шпион был создан, можно использовать различные методы, чтобы проверить, был ли вызван отслеживаемый метод.

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

Пример:

const spy = jest.spyOn(user, 'getName');
user.getName();
console.log(spy.mock.calls); // [['John Doe']]

mock.results — массив всех результатов вызова метода, включая значения, возвращенные после выполнения.

Пример:

const spy = jest.spyOn(user, 'getName').mockReturnValue('Jane Doe');
console.log(user.getName()); // 'Jane Doe'
console.log(spy.mock.results); // [{ type: 'return', value: 'Jane Doe' }]

Модификация поведения метода с помощью mockReturnValue() и mockImplementation()

Шпион позволяет не только наблюдать за вызовами методов, но и изменять их поведение.

mockReturnValue() — задает фиксированное возвращаемое значение для отслеживаемого метода.

Пример:

const spy = jest.spyOn(user, 'getName').mockReturnValue('Jane Doe');
console.log(user.getName()); // 'Jane Doe'

mockImplementation() — позволяет задать кастомную реализацию для метода, которую шпион будет вызывать вместо оригинальной.

Пример:

const spy = jest.spyOn(user, 'getName').mockImplementation(() => 'Custom Name');
console.log(user.getName()); // 'Custom Name'

Очистка шпионов

После выполнения тестов важно очищать шпионов, чтобы они не влияли на другие тесты. Jest предоставляет метод mockRestore() для восстановления оригинального поведения метода.

Пример:

const spy = jest.spyOn(user, 'getName').mockReturnValue('Jane Doe');
user.getName();
spy.mockRestore(); // Восстановит оригинальную функцию
console.log(user.getName()); // 'John Doe'

Также можно использовать jest.clearAllMocks() или jest.resetAllMocks() для очистки всех моков и шпионов на уровне теста.

Использование шпионов с внешними зависимостями

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

Пример использования шпионов с внешним API:

const fetchData = async () => {
  const response = await fetch('https://api.example.com');
  return response.json();
};

test('fetchData вызывает fetch', async () => {
  const spy = jest.spyOn(global, 'fetch').mockResolvedValue({
    json: jest.fn().mockResolvedValue({ data: 'test' })
  });

  const result = await fetchData();
  expect(spy).toHaveBeenCalledWith('https://api.example.com');
  expect(result).toEqual({ data: 'test' });
  spy.mockRestore();
});

В этом примере создается шпион на глобальный метод fetch, и мы проверяем, что он был вызван с правильным URL и что результат выполнения соответствует ожидаемому.

Пример: использование с классами

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

Пример:

class User {
  getName() {
    return 'John Doe';
  }
}

test('User.getName вызывается', () => {
  const user = new User();
  const spy = jest.spyOn(user, 'getName').mockReturnValue('Jane Doe');

  expect(user.getName()).toBe('Jane Doe');
  spy.mockRestore();
});

В данном примере шпион используется для метода getName класса User, и мы заменяем возвращаемое значение на «Jane Doe».

Выводы

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

  • Отслеживание вызовов метода и его аргументов.
  • Модификация возвращаемых значений с помощью mockReturnValue() или mockImplementation().
  • Очистка шпионов после выполнения тестов.
  • Интеграция с внешними сервисами и библиотеками.

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