В модульном и интеграционном тестировании React-приложений важна
строгая изоляция тестов. Каждый тест должен выполняться в предсказуемом
состоянии, не зависящем от предыдущих запусков. Для этого в экосистеме
JavaScript-тестирования используются хуки beforeEach и
afterEach, предоставляемые тест-раннерами (чаще всего Jest
или Vitest). В контексте React Testing Library эти хуки применяются для
setup и cleanup тестового
окружения.
beforeEach в
setupbeforeEach выполняется перед каждым
тестом (test / it) внутри одного
describe-блока. Его задача — подготовить окружение в
единообразном состоянии.
Типовые сценарии использования:
import { render, screen } from '@testing-library/react';
import UserProfile from './UserProfile';
describe('UserProfile', () => {
beforeEach(() => {
render(<UserProfile />);
});
test('отображает имя пользователя', () => {
expect(screen.getByText('Иван')).toBeInTheDocument();
});
test('отображает аватар', () => {
expect(screen.getByRole('img')).toBeInTheDocument();
});
});
Рендер выполняется один раз на каждый тест, что гарантирует чистое DOM-состояние.
Часто компонент зависит от пропсов, контекста или провайдеров. В этом
случае beforeEach удобно использовать вместе с фабрикой или
конфигурационным объектом.
let defaultProps;
beforeEach(() => {
defaultProps = {
isAdmin: false,
userName: 'Иван',
};
});
Или с кастомным рендером:
const renderWithProviders = (ui) => {
return render(
<AuthProvider>
<ThemeProvider>{ui}</ThemeProvider>
</AuthProvider>
);
};
beforeEach(() => {
renderWithProviders(<Dashboard />);
});
Такой подход:
afterEach
и cleanup тестового окруженияafterEach выполняется после каждого
теста и предназначен для очистки побочных эффектов.
В React Testing Library очистка DOM выполняется автоматически через
cleanup, если используется стандартная конфигурация Jest.
Однако afterEach остаётся критически важным в ряде
случаев:
afterEach(() => {
jest.clearAllMocks();
});
Это гарантирует, что вызовы mock-функций не «протекут» в следующий тест.
cleanup и контроль жизненного циклаИногда автоматическая очистка недостаточна или отключена (например, в нестандартной конфигурации).
import { cleanup } from '@testing-library/react';
afterEach(() => {
cleanup();
});
Явный вызов полезен при:
createPortal).beforeEach и afterEach поддерживают
async/await, что критично для тестирования эффектов,
запросов и инициализации состояния.
beforeEach(async () => {
await fetchMock.enableMocks();
fetchMock.mockResponseOnce(JSON.stringify({ name: 'Иван' }));
render(<UserProfile />);
});
afterEach(async () => {
await fetchMock.disableMocks();
});
Асинхронный teardown особенно важен при:
При использовании jest.useFakeTimers() состояние
таймеров должно быть строго контролируемым.
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.runOnlyPendingTimers();
jest.useRealTimers();
});
Такой шаблон предотвращает зависание тестов и утечки таймеров между кейсами.
describe и порядок выполненияХуки выполняются иерархически:
beforeEach внешнего describe →
внутреннего;afterEach — в обратном порядке.describe('Auth', () => {
beforeEach(() => {
// общий setup
});
describe('Logged in user', () => {
beforeEach(() => {
// дополнительный setup
});
test('...', () => {});
});
});
Это позволяет:
beforeEach.beforeEach и afterEachИзбыточная логика
Сложные вычисления, условия и ветвления в хуках снижают читаемость тестов.
Скрытые зависимости
Тесты, которые неявно зависят от beforeEach, труднее
читать и поддерживать. Критически важные данные должны быть видны в
самом тесте или в явно названных фабриках.
Мутация общих объектов
let user;
beforeEach(() => {
user = { name: 'Иван' };
});
Допустимо, но только при гарантии, что объект не мутируется в тестах. В противном случае — глубокое клонирование или фабрика.
Хуки должны:
Оптимальный стиль — минимальный beforeEach + явная
логика в теле теста.
beforeEach(() => {
render(<LoginForm />);
});
test('отправляет форму', async () => {
userEvent.type(screen.getByLabelText(/email/i), 'test@mail.com');
userEvent.click(screen.getByRole('button'));
});
Такой подход сохраняет прозрачность и делает тесты самодокументируемыми.
React Testing Library продвигает принципы:
beforeEach и afterEach служат
вспомогательными инструментами, обеспечивающими стабильную среду, но не
должны становиться центром тестовой логики.