Как мокать Api-запросы в jest для тестирования javascript-кода

Введение в мокинг 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')`. Это отличный способ централизовать логику моков и не дублировать код.

Заключение

Как мокать (mock) API-запросы в Jest - иллюстрация

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

Прокрутить вверх