Введение в мокинг API-запросов с использованием Jest
Когда вы работаете с JavaScript-приложениями, особенно с React, Node.js или любым другим фреймворком, важно уметь проводить тестирование API с Jest. Это позволяет убедиться, что ваш код корректно обрабатывает ответы внешних сервисов. Однако при написании юнит-тестов напрямую обращаться к реальному API — плохая практика. Вместо этого следует мокать API-запросы в Jest, чтобы избежать нестабильности, зависящей от сети или стороннего сервиса.
Шаг 1: Подготовка окружения для мокинга
Установка необходимых зависимостей
Jest уже включает в себя мощный функционал для мокинга, поэтому дополнительных пакетов обычно не требуется. Однако если вы используете `axios` или `fetch`, может понадобиться установить дополнительные утилиты. Например, при работе с `fetch`, стоит подключить `whatwg-fetch` или использовать `jest-fetch-mock`.
```bash
npm install --save-dev jest-fetch-mock
```
Затем подключите его в файле конфигурации или в setup-файле:
```js
// jest.setup.js
require('jest-fetch-mock').enableMocks();
```
Совет для новичков
Если вы только начинаете разбираться, как использовать mock в Jest, начните с простых функций, а не сразу с сетевых запросов. Это поможет лучше понять, как работает мокинг и как контролировать поведение зависимостей.
Шаг 2: Мокинг fetch-запросов
Простой пример с fetch
Рассмотрим функцию, которая делает API-запрос:
```js
export async function getUserData(userId) {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) throw new Error('Network error');
return response.json();
}
```
Чтобы протестировать эту функцию, мы можем мокать API-запросы в Jest следующим образом:
```js
import { getUserData } from './api';
beforeEach(() => {
fetch.resetMocks();
});
test('возвращает данные пользователя', async () => {
fetch.mockResponseOnce(JSON.stringify({ id: 1, name: 'Alice' }));
const data = await getUserData(1);
expect(data).toEqual({ id: 1, name: 'Alice' });
expect(fetch).toHaveBeenCalledWith('/api/users/1');
});
```
Здесь мы используем `mockResponseOnce`, чтобы задать фейковый ответ от сервера. Такой подход отлично подходит для тестирования API с Jest, особенно когда важна предсказуемость и скорость выполнения.
Распространённые ошибки
Одна из частых проблем — забыть сбросить моки между тестами с помощью `fetch.resetMocks()`. Это может привести к «утечке» состояния между тестами, что делает результат непредсказуемым. Также не забывайте проверять, что мок возвращает ожидаемую структуру данных — иначе тест может упасть не из-за логики функции, а из-за некорректного мока.
Шаг 3: Мокинг axios-запросов
Использование Jest для mock axios
Если вы используете axios, то мокать API-запросы в Jest можно с помощью встроенного мокинга модулей. Jest позволяет перехватывать вызовы и подменять поведение импортируемых зависимостей.
```js
// api.js
import axios from 'axios';
export async function getPosts() {
const response = await axios.get('/api/posts');
return response.data;
}
```
```js
// api.test.js
import axios from 'axios';
import { getPosts } from './api';
jest.mock('axios');
test('получает список постов', async () => {
axios.get.mockResolvedValueOnce({ data: [{ id: 1, title: 'Post' }] });
const posts = await getPosts();
expect(posts).toEqual([{ id: 1, title: 'Post' }]);
expect(axios.get).toHaveBeenCalledWith('/api/posts');
});
```
Здесь мы используем `jest.mock('axios')`, чтобы заменить оригинальный модуль мок-версией. Затем через `mockResolvedValueOnce` задаём ответ. Этот способ mock API в Jest особенно удобен, если в проекте активно используется axios.
Полезный совет
Если вы работаете с несколькими API в разных модулях, стоит создавать отдельные файлы с моками и переиспользовать их. Это сделает тесты более читаемыми и упростит поддержку.
Шаг 4: Мокинг ошибок и исключений
Кроме успешных ответов, важно тестировать, как ваш код обрабатывает ошибки. В случае с fetch:
```js
fetch.mockRejectOnce(new Error('Сервер недоступен'));
```
А для axios:
```js
axios.get.mockRejectedValueOnce(new Error('500 Internal Server Error'));
```
Такой подход позволяет убедиться, что функция корректно реагирует на сбои: вызывает обработчики ошибок, логирует исключения или возвращает ожидаемые значения по умолчанию.
Частая ошибка
Новички часто забывают, что мок должен соответствовать поведению реального API. Например, если ваш API возвращает 404 с телом ответа, мок тоже должен симулировать эту ситуацию. Иначе вы получите ложноположительный результат теста — он пройдёт, но поведение в реальной среде окажется другим.
Шаг 5: Создание универсальных моков
Когда вы тестируете множество компонентов, которые используют одну и ту же API-функцию, удобно использовать универсальные моки. Создайте файл `__mocks__/axios.js` и добавьте туда следующее:
```js
export default {
get: jest.fn(),
post: jest.fn(),
put: jest.fn(),
delete: jest.fn(),
};
```
Jest автоматически подхватит этот файл при вызове `jest.mock('axios')`. Это отличный способ централизовать логику моков и не дублировать код.
Заключение

Мокинг сетевых запросов — важный аспект качественного тестирования. Использование Jest для mock позволяет изолировать тесты, сделать их надёжными и независимыми от внешней среды. Независимо от того, работаете ли вы с fetch или axios, важно понимать, как использовать mock в Jest грамотно. Следите за тем, чтобы моки были реалистичными, сбрасывались между тестами и отражали реальные сценарии. Это поможет избежать ложных результатов и обеспечит стабильность вашего кода на всех этапах разработки.



