Зачем нужны моки и фикстуры?
Когда ваш компонент загружает или отправляет данные на сервер (например, через запросы к API), вам нужно быть уверенным, что всё работает как следует. Однако тестировать это на реальном сервере — плохая идея. Почему?
- Зависимость от внешней среды: если сервер упадёт или изменится, ваши тесты начнут падать.
- Скорость: тесты, отправляющие реальные запросы, медленнее. Нам нужно быстро.
- Конфиденциальность данных: некоторые данные нельзя отправлять и использовать в реальных API.
И вот тут на помощь приходят моки и фикстуры.
- Моки — фейковые реализации функций или объектов, которые подменяют реальные зависимости. Например, если компонент вызывает функцию
fetch, вы можете замокать её и вернуть тестовые данные. - Фикстуры — заранее подготовленные данные, которые используются в ваших тестах. Это можно представить как "шаблонные" данные.
Создание моков для API-вызовов
Jest предоставляет встроенные функции для создания моков. Чтобы замокать вызов API, вам нужно подменить соответствующую функцию.
Пример: наш компонент использует fetch для получения данных. Давайте замокаем его.
// UserDetails.tsx — компонент
import React, { useEffect, useState } from 'react';
interface User {
id: number;
name: string;
email: string;
}
const UserDetails: React.FC = () => {
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
const fetchUser = async () => {
const response = await fetch('https://api.example.com/user/1');
const data = await response.json();
setUser(data);
};
fetchUser();
}, []);
if (!user) {
return <div>Loading...</div>;
}
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
};
export default UserDetails;
Теперь создадим тест для этого компонента с моками.
// UserDetails.test.tsx — тест
import React from 'react';
import { render, screen } from '@testing-library/react';
import UserDetails from './UserDetails';
// Мок для global.fetch
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ id: 1, name: 'John Doe', email: 'john.doe@example.com' }),
})
) as jest.Mock;
test('renders user details after API call', async () => {
render(<UserDetails />);
// Ожидаем, что "загрузка" будет отображена
expect(screen.getByText(/Loading/i)).toBeInTheDocument();
// Ожидаем, что данные пользователя появятся
const name = await screen.findByText(/John Doe/i); // findByText ждёт появления элемента
expect(name).toBeInTheDocument();
});
Типичные ошибки при работе с моками
- Пропустили сброс мока между тестами: если ваш мок используется в нескольких тестах, всегда сбрасывайте его состояние с помощью
jest.clearAllMocks()перед каждым тестом. - Закомментировали вызов мока: если вы забыли замокать
fetch, то тест может провалиться из-за реального вызова.
Использование фикстур для подготовки данных
Представьте, что мы часто в наших тестах возвращаем одного и того же пользователя. Вместо того чтобы дублировать данные в каждом тесте, мы выносим их в отдельный файл.
Создадим фикстуру:
// fixtures/user.ts
export const userFixture = {
id: 1,
name: 'John Doe',
email: 'john.doe@example.com',
};
Теперь мы можем использовать эту фикстуру в тестах:
// UserDetails.test.tsx — тест с фикстурой
import React from 'react';
import { render, screen } from '@testing-library/react';
import UserDetails from './UserDetails';
import { userFixture } from './fixtures/user';
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve(userFixture),
})
) as jest.Mock;
test('renders user details after API call', async () => {
render(<UserDetails />);
const name = await screen.findByText(userFixture.name);
expect(name).toBeInTheDocument();
});
Использование фикстур помогает сделать тесты более читаемыми и поддерживаемыми.
Использование библиотеки msw для Mock API
Если ваш компонент взаимодействует с несколькими API или вы хотите точнее замокать сетевые запросы, библиотека MSW (Mock Service Worker) становится вашим спасителем.
Установка MSW
Установите библиотеку:
npm install msw --save-dev
Настройка MSW
- Создайте файл с моком API.
// mocks/handlers.ts
import { rest } from 'msw';
import { userFixture } from '../fixtures/user';
export const handlers = [
rest.get('https://api.example.com/user/1', (req, res, ctx) => {
return res(ctx.json(userFixture));
}),
];
- Настройте MSW в тестах:
// setupTests.ts
import { setupServer } from 'msw/node';
import { handlers } from './mocks/handlers';
const server = setupServer(...handlers);
// Запуск сервера перед всеми тестами
beforeAll(() => server.listen());
// Сбрасываем обработчики после каждого теста
afterEach(() => server.resetHandlers());
// Останавливаем сервер после завершения тестов
afterAll(() => server.close());
- Используйте в тестах:
// UserDetails.test.tsx — тест с MSW
import React from 'react';
import { render, screen } from '@testing-library/react';
import UserDetails from './UserDetails';
test('renders user details after API call', async () => {
render(<UserDetails />);
const name = await screen.findByText(/John Doe/i);
expect(name).toBeInTheDocument();
});
Моки vs фикстуры: когда использовать?
- Моки: подходят для имитации поведения функций и внешних зависимостей.
- Фикстуры: используются для управления тестовыми данными (будь то статический JSON или фальшивые данные объектов).
Совместное использование моков и фикстур помогает вам писать тесты, которые легко читать, поддерживать и масштабировать.
Советы и типичные ошибки при тестировании API
Тестирование API часто вызывает путаницу. Вот несколько советов, чтобы избежать проблем:
- Всегда сбрасывайте состояние моков между тестами. Используйте
jest.clearAllMocks()илиjest.resetModules()в блокеafterEach. - Проверяйте не только успешные кейсы, но и ошибки. Например, что компонент корректно обрабатывает ошибки API (например, возвращает "Произошла ошибка").
- Если моки слишком сложны, подумайте об
msw. MSW позволяет легко создать реалистичное поведение API. - Держите ваши мок-данные и фикстуры компактными и легко читаемыми. Большие файлы сложно отлаживать.
Тестирование взаимодействия API — важная часть стабильности приложения. Когда вы убедитесь, что запросы и ответы работают корректно, вы автоматически почувствуете себя спокойней перед релизами.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ