Контексты в тестировании — важный аспект, обеспечивающий изоляцию и управление состоянием в тестах. В Jest контекст играет ключевую роль, когда требуется имитировать различные среды, сценарии или состояния в процессе тестирования функций, компонентов или модулей. Для работы с контекстом используется несколько методов, включая мокирование зависимостей, настройки глобальных объектов и использование контекстов в React. Понимание того, как правильно работать с контекстом, позволяет писать тесты, которые являются более точными и воспроизводимыми.
Мокирование (mocking) — это процесс замены реальных зависимостей
фальшивыми объектами или функциями, что позволяет изолировать
тестируемый код от внешних факторов. В Jest для мокирования контекста
можно использовать функцию jest.mock(), которая заменяет
модули или функции на моки.
Пример мокирования контекста:
// Модуль с функцией, которую нужно замокать
export const getUserInfo = () => {
return fetch('/api/user')
.then(response => response.json());
};
// Тест, где мы мокируем getUserInfo
import { getUserInfo } from './getUserInfo';
jest.mock('./getUserInfo');
test('должен вернуть данные пользователя', async () => {
getUserInfo.mockResolvedValue({ name: 'Иван', age: 25 });
const result = await getUserInfo();
expect(result).toEqual({ name: 'Иван', age: 25 });
});
В этом примере мы заменили реальную функцию getUserInfo
на мок, который возвращает заранее заданный результат. Это позволяет
тестировать код, не выполняя реальный запрос к серверу.
Jest предоставляет возможность работы с глобальными объектами, такими
как window, document,
localStorage, что удобно при тестировании функционала,
который зависит от них. Для их настройки можно использовать хуки, такие
как beforeAll(), beforeEach(),
afterAll(), afterEach().
Пример настройки глобальных объектов:
beforeAll(() => {
global.localStorage = {
getItem: jest.fn(),
setItem: jest.fn(),
};
});
test('проверка вызова localStorage', () => {
localStorage.setItem('token', 'abc123');
expect(localStorage.setItem).toHaveBeenCalledWith('token', 'abc123');
});
В этом примере мы заменили стандартный localStorage на
мок, чтобы протестировать его использование без взаимодействия с
реальным браузером.
React Testing LibraryReact использует контексты для управления состоянием приложения,
особенно когда нужно передавать данные через несколько уровней
компонентов. Jest вместе с React Testing Library позволяет
эффективно тестировать компоненты, использующие контекст.
Для тестирования компонентов с контекстом необходимо обернуть компонент в провайдер контекста и передать необходимые данные.
Пример тестирования компонента с контекстом:
import { render, screen } from '@testing-library/react';
import { UserContext, UserProvider } from './UserContext';
import UserProfile from './UserProfile';
test('отображает информацию о пользователе', () => {
const user = { name: 'Анна', age: 30 };
render(
<UserProvider value={user}>
<UserProfile />
</UserProvider>
);
expect(screen.getByText('Анна')).toBeInTheDocument();
expect(screen.getByText('30')).toBeInTheDocument();
});
В этом примере мы используем провайдер контекста
UserProvider для того, чтобы передать данные о пользователе
в компонент UserProfile. Это позволяет тестировать
компонент, не полагаясь на внешние зависимости.
jest.setup.jsЕсли необходимо выполнить настройку глобальных переменных или модулей
перед всеми тестами, можно использовать файл jest.setup.js.
В этом файле можно определить, какие глобальные объекты будут доступны в
тестах, или настроить поведение некоторых библиотек.
Пример настройки через jest.setup.js:
// jest.setup.js
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ name: 'Иван', age: 25 }),
})
);
Этот файл будет выполнен до начала всех тестов, что позволяет избежать дублирования настройки в каждом тесте.
jest.spyOn()Для тестирования функций, которые зависят от контекста или состояния,
можно использовать метод jest.spyOn(). Он позволяет создать
шпион на методах объектов и проверять, как они были вызваны.
Пример использования jest.spyOn():
import { getUserInfo } from './userApi';
test('проверка вызова getUserInfo', () => {
const spy = jest.spyOn(global, 'fetch');
spy.mockResolvedValue({
json: jest.fn().mockResolvedValue({ name: 'Иван' }),
});
getUserInfo();
expect(spy).toHaveBeenCalledWith('/api/user');
spy.mockRestore();
});
Здесь мы используем jest.spyOn() для шпионажа на
глобальном методе fetch, проверяя, что он был вызван с
нужным аргументом.
Контекст может также включать асинхронные операции, например, запросы
к серверу. В таких случаях важно правильно настроить тесты, чтобы они
ожидали завершения асинхронных операций. Jest предоставляет несколько
способов работы с асинхронностью, включая async/await,
done и возвращение промисов.
Пример асинхронного теста:
test('асинхронный запрос данных', async () => {
const data = await fetchDataFromApi();
expect(data).toEqual({ name: 'Иван', age: 30 });
});
Когда тест зависит от асинхронных операций, важно дождаться завершения этих операций перед проверкой результатов.
Для более сложных тестов, которые включают интеграцию нескольких частей системы, часто необходимо замокировать контекст на более высоком уровне. Это помогает изолировать тестируемую часть и предотвратить непредсказуемые побочные эффекты от других частей системы.
Пример интеграционного теста с мокированием контекста:
import { render, screen } from '@testing-library/react';
import { MyComponent } from './MyComponent';
import { UserContext } from './UserContext';
jest.mock('./UserContext', () => ({
...jest.requireActual('./UserContext'),
useUser: jest.fn(),
}));
test('интеграционный тест с мокированным контекстом', () => {
const mockUser = { name: 'Анна', age: 25 };
useUser.mockReturnValue(mockUser);
render(<MyComponent />);
expect(screen.getByText('Анна')).toBeInTheDocument();
expect(screen.getByText('25')).toBeInTheDocument();
});
В данном примере мы мокируем хук useUser, который
используется в компоненте MyComponent, и проверяем, что
компонент корректно отображает данные, полученные из контекста.
Тестирование контекста в Jest играет важную роль в создании стабильных и изолированных тестов. Использование моков, настройка глобальных объектов и правильное использование контекстов в React позволяют создавать надежные тесты, которые отражают реальное поведение приложения. Знание различных техник работы с контекстом помогает повысить качество тестирования, улучшить поддержку кода и ускорить процесс разработки.