При тестировании приложений на базе TanStack Router критически важно изолировать поведение компонентов от реального роутинга. Мокирование роутера позволяет проверять логику навигации, рендеринга и взаимодействия с маршрутами без необходимости запускать полноценное приложение или эмулировать браузерную историю.
Изоляция зависимостей Компоненты не должны напрямую обращаться к реальному экземпляру роутера. Вместо этого создаётся мок-объект, который имитирует API роутера:
const mockRouter = {
navigate: jest.fn(),
getCurrentRoute: jest.fn(),
subscribe: jest.fn(),
};
Такой объект позволяет отслеживать вызовы методов, имитировать текущий маршрут и проверять реакции компонентов на навигацию.
Имитация маршрутов TanStack Router опирается на маршруты, которые определяют путь, параметры и логику загрузки данных. При тестировании можно создать фиктивный набор маршрутов:
const routes = [
{ path: '/', component: HomeComponent },
{ path: '/profile/:id', component: ProfileComponent },
];
const mockRoute = {
pathname: '/profile/42',
params: { id: '42' },
};
mockRouter.getCurrentRoute.mockReturnValue(mockRoute);
Это позволяет тестировать компоненты, которые используют параметры маршрута, без необходимости реальной навигации.
Мокирование навигации Метод
navigate используется для переходов между маршрутами. В
тестах важно проверять, что вызовы происходят корректно:
import { fireEvent } from '@testing-library/react';
test('кнопка перенаправляет на профиль', () => {
const { getByText } = render(<ProfileButton router={mockRouter} />);
fireEvent.click(getByText('Перейти в профиль'));
expect(mockRouter.navigate).toHaveBeenCalledWith('/profile/42');
});Подписка на изменения маршрута Компоненты могут
подписываться на изменения маршрута через router.subscribe.
Мок позволяет имитировать события:
const callback = jest.fn();
mockRouter.subscribe.mockImplementation(cb => {
cb(mockRoute);
return () => {};
});
render(<SomeComponent router={mockRouter} />);
expect(callback).toHaveBeenCalledWith(mockRoute);Использование MemoryRouter TanStack Router
предоставляет возможность работы с “памятным” роутером
(MemoryRouter), который не взаимодействует с URL браузера.
Это облегчает тестирование навигации и рендеринга маршрутов в
изолированной среде.
Мокирование хранилища состояний маршрута Для проверки редиректов и условного рендеринга можно создать фиктивное хранилище маршрутов и управлять им вручную:
const routeStore = createRouteStore({ initialRoute: '/' });
routeStore.setRoute('/profile/42');
render(<App router={{ ...mockRouter, routeStore }} />);jest.fn() и
jest.spyOn() для отслеживания вызовов методов и
подписок.router.subscribe, могут вести себя некорректно без
корректного мокирования.useParams или route.params, нужно
явно задавать значения в мок-объекте.test('рендер компонента с параметрами маршрута и переход на другой маршрут', () => {
const mockRouter = {
navigate: jest.fn(),
getCurrentRoute: jest.fn(() => ({ pathname: '/profile/42', params: { id: '42' } })),
subscribe: jest.fn((cb) => { cb({ pathname: '/profile/42', params: { id: '42' } }); return () => {}; }),
};
const { getByText } = render(<ProfilePage router={mockRouter} />);
expect(getByText('Профиль пользователя 42')).toBeInTheDocument();
fireEvent.click(getByText('Редактировать'));
expect(mockRouter.navigate).toHaveBeenCalledWith('/profile/42/edit');
});
Такой подход позволяет полностью тестировать поведение компонентов в контексте роутинга, при этом исключая зависимости от браузерного API и обеспечивая стабильность тестов.
Мокирование роутера становится особенно полезным при тестировании больших приложений с динамическими маршрутами и условным рендерингом, так как оно обеспечивает контроль над состоянием навигации и позволяет проверять любые сценарии без реальных переходов.