MemoryRouter в тестах

MemoryRouter — это компонент из библиотеки React Router, предназначенный для работы с маршрутизацией в памяти. В отличие от BrowserRouter или HashRouter, которые используют URL браузера для управления состоянием маршрутов, MemoryRouter хранит все маршруты исключительно в памяти. Это делает его идеальным инструментом для тестирования компонентов, зависящих от маршрутизации, без необходимости запускать реальный браузер или изменять адресную строку.


Основные свойства MemoryRouter

  • initialEntries: массив строк или объектов, задающий последовательность маршрутов, с которых начинается тест. Позволяет моделировать навигацию и проверять переходы между маршрутами.

    <MemoryRouter initialEntries={['/home', '/about']}>
      <App />
    </MemoryRouter>
  • initialIndex: число, указывающее на индекс активного маршрута в массиве initialEntries. Полезно для тестов, когда нужно установить определённый маршрут как текущий.

    <MemoryRouter initialEntries={['/home', '/about']} initialIndex={1}>
      <App />
    </MemoryRouter>
  • children: дочерние элементы, обычно это компонент приложения или компонент, который нужно протестировать с маршрутизацией.


Использование MemoryRouter для тестирования

1. Проверка корректного рендера компонентов по маршрутам

MemoryRouter позволяет задать конкретный путь и проверить, что соответствующий компонент отображается корректно.

import { render, screen } from '@testing-library/react';
import { MemoryRouter, Routes, Route } from 'react-router-dom';
import Home from './Home';
import About from './About';

test('рендерит компонент Home по маршруту /', () => {
  render(
    <MemoryRouter initialEntries={['/']}>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </MemoryRouter>
  );
  expect(screen.getByText('Добро пожаловать на главную')).toBeInTheDocument();
});

2. Тестирование навигации между маршрутами

Можно проверить переход между маршрутами и правильное обновление отображаемого компонента без использования настоящей навигации в браузере.

import { fireEvent } from '@testing-library/react';
import { MemoryRouter, Routes, Route } from 'react-router-dom';
import App from './App';

test('переход с Home на About', () => {
  render(
    <MemoryRouter initialEntries={['/']}>
      <App />
    </MemoryRouter>
  );

  fireEvent.click(screen.getByText('О нас'));
  expect(screen.getByText('Информация о компании')).toBeInTheDocument();
});

3. Тестирование редиректов

MemoryRouter позволяет имитировать редиректы и проверять поведение компонентов при изменении маршрута.

import { Navigate } from 'react-router-dom';

test('редирект с /login на /dashboard', () => {
  render(
    <MemoryRouter initialEntries={['/login']}>
      <Routes>
        <Route path="/login" element={<Navigate to="/dashboard" />} />
        <Route path="/dashboard" element={<div>Панель управления</div>} />
      </Routes>
    </MemoryRouter>
  );

  expect(screen.getByText('Панель управления')).toBeInTheDocument();
});

Полезные советы при использовании MemoryRouter

  • Тестирование вложенных маршрутов: MemoryRouter отлично подходит для проверки работы вложенных Route. Можно задавать начальный путь через initialEntries с глубокими вложенными маршрутами (/dashboard/settings).

  • События навигации: для тестов важно использовать fireEvent или userEvent из @testing-library/react для имитации кликов по ссылкам (<Link>), чтобы проверить работу маршрутизации без реального изменения URL.

  • Состояние истории: MemoryRouter хранит историю переходов в массиве history.entries, что позволяет проверять порядок навигации и использовать методы history.push и history.replace внутри тестов.

  • Совместимость с Jest: MemoryRouter не зависит от DOM браузера, поэтому идеально интегрируется с Jest и другими тестовыми раннерами, поддерживающими Node.js среду.


Примеры сложных сценариев

Тестирование переходов с параметрами

<Route path="/profile/:id" element={<Profile />} />
render(
  <MemoryRouter initialEntries={['/profile/42']}>
    <Routes>
      <Route path="/profile/:id" element={<Profile />} />
    </Routes>
  </MemoryRouter>
);

expect(screen.getByText('Профиль пользователя 42')).toBeInTheDocument();

Тестирование условной навигации

<Route path="/secret" element={isLoggedIn ? <Secret /> : <Navigate to="/login" />} />
render(
  <MemoryRouter initialEntries={['/secret']}>
    <Routes>
      <Route path="/secret" element={isLoggedIn ? <Secret /> : <Navigate to="/login" />} />
      <Route path="/login" element={<Login />} />
    </Routes>
  </MemoryRouter>
);

expect(screen.getByText('Авторизация')).toBeInTheDocument();

MemoryRouter обеспечивает полный контроль над состоянием маршрутов без взаимодействия с браузером, что делает его универсальным инструментом для модульного тестирования компонентов React с маршрутизацией. Его возможности позволяют моделировать переходы, редиректы, вложенные маршруты и параметры URL, создавая надежные и воспроизводимые тесты.