jest.spyOn() для отслеживания методов

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

Основные возможности jest.spyOn()

jest.spyOn() позволяет:

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

Синтаксис и базовое использование

Метод jest.spyOn() принимает два обязательных параметра:

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

Пример:

const obj = {
  method: (a, b) => a + b,
};

const spy = jest.spyOn(obj, 'method');

// Вызов метода
obj.method(1, 2);

// Проверка вызова
expect(spy).toHaveBeenCalled();
expect(spy).toHaveBeenCalledWith(1, 2);

В этом примере мы создали объект с методом, шпионем за этим методом с помощью jest.spyOn(), вызываем метод и проверяем, что он был вызван с правильными аргументами.

Подменить реализацию метода

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

Пример:

const obj = {
  fetchData: () => {
    return 'real data';
  },
};

const spy = jest.spyOn(obj, 'fetchData').mockReturnValue('mocked data');

// Теперь метод fetchData вернёт 'mocked data'
console.log(obj.fetchData()); // 'mocked data'

expect(spy).toHaveBeenCalled();

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

Важные методы для работы с jest.spyOn()

  • mockReturnValue(value): позволяет задать значение, которое будет возвращено при вызове отслеживаемого метода.

  • mockImplementation(fn): позволяет задать произвольную реализацию для отслеживаемого метода, что полезно для имитации сложных сценариев.

  • mockRestore(): восстанавливает оригинальное поведение метода, если он был шпионен с помощью jest.spyOn().

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

const obj = {
  fetchData: () => 'real data',
};

const spy = jest.spyOn(obj, 'fetchData').mockImplementation(() => 'mocked data');

// Теперь fetchData будет возвращать 'mocked data', а не 'real data'
console.log(obj.fetchData()); // 'mocked data'

spy.mockRestore(); // Восстанавливаем исходную функцию

console.log(obj.fetchData()); // 'real data'

Использование jest.spyOn() с классами

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

Пример с классом:

class MyClass {
  myMethod(a, b) {
    return a + b;
  }
}

const instance = new MyClass();
const spy = jest.spyOn(instance, 'myMethod');

// Вызов метода
instance.myMethod(2, 3);

// Проверка
expect(spy).toHaveBeenCalled();
expect(spy).toHaveBeenCalledWith(2, 3);

В этом примере мы создаём экземпляр класса, шпионяем за методом myMethod, а затем проверяем, что метод был вызван с правильными аргументами.

Шпион за методами сторонних библиотек

jest.spyOn() также полезен для тестирования взаимодействий с внешними зависимостями, например, при тестировании вызовов сторонних библиотек.

Пример с использованием стороннего метода:

const axios = require('axios');
jest.spyOn(axios, 'get').mockResolvedValue({ data: 'mocked data' });

axios.get('https://api.example.com/data').then(response => {
  console.log(response.data); // 'mocked data'
});

Здесь мы шпионем за методом get из библиотеки axios и возвращаем “мокированные” данные. Это позволяет тестировать логику взаимодействия с внешними сервисами без реальных сетевых запросов.

Ограничения и предостережения

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

  2. Поведение с асинхронными методами: При работе с асинхронными методами следует учитывать, что вызовы, которые возвращают промисы, также можно контролировать с помощью методов вроде mockResolvedValue() или mockRejectedValue().

  3. Невозможность отслеживания конструкторов: jest.spyOn() не может использоваться для отслеживания вызовов конструкторов, так как это не является методом объекта. В таких случаях используют другие подходы, например, шпионаж на методы экземпляров.

Пример использования jest.spyOn() в интеграционных тестах

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

Пример интеграционного теста:

class ApiService {
  fetchData() {
    return fetch('https://api.example.com/data').then(response => response.json());
  }
}

const apiService = new ApiService();
jest.spyOn(apiService, 'fetchData').mockResolvedValue({ data: 'mocked data' });

test('fetchData returns mocked data', async () => {
  const data = await apiService.fetchData();
  expect(data).toEqual({ data: 'mocked data' });
});

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

Заключение

Метод jest.spyOn() является мощным инструментом для отслеживания и манипулирования поведением методов и функций во время тестирования. Он позволяет эффективно проверять взаимодействия в системе, имитировать определённые поведения и изолировать код от внешних зависимостей. Правильное использование jest.spyOn() значительно улучшает качество тестов и делает их более предсказуемыми.