При тестировании компонентов Vue, которые используют Vue Router для навигации или работы с маршрутами, часто возникает необходимость изолировать компонент от реального роутера. Это позволяет проверять поведение компонента без создания полного приложения или зависимости от состояния маршрутов. В таких случаях используется мок (mock) Vue Router.
Для начала необходимы базовые импорты:
import { mount } from '@vue/test-utils';
import { createRouter, createWebHistory } from 'vue-router';
import ComponentUnderTest from '@/components/ComponentUnderTest.vue';
Мок роутера можно реализовать несколькими способами: полностью
эмулировать объект router, либо создать реальный роутер с
ограниченным набором маршрутов.
Простейший мок методов маршрутизатора:
const mockRouter = {
push: jest.fn(),
replace: jest.fn(),
currentRoute: {
value: { path: '/home' }
}
};
Здесь ключевое:
push и replace — методы навигации, которые
можно отслеживать через Jest.currentRoute.value — объект текущего маршрута,
аналогичный объекту route в Vue Router 4.Для передачи мока в компонент используется опция
global.plugins или global.mocks:
const wrapper = mount(ComponentUnderTest, {
global: {
mocks: {
$router: mockRouter,
$route: mockRouter.currentRoute
}
}
});
Варианты:
$router — предоставляет доступ к методам
навигации.$route — содержит данные текущего маршрута
(params, query, name,
path).После этого можно проверять вызовы методов:
await wrapper.find('button.navigate').trigger('click');
expect(mockRouter.push).toHaveBeenCalledWith('/about');
Иногда требуется протестировать реакцию компонента на реальные переходы или guards. Для этого создаётся роутер с минимальными маршрутами:
const routes = [
{ path: '/home', component: { template: '<div>Home</div>' } },
{ path: '/about', component: { template: '<div>About</div>' } }
];
const router = createRouter({
history: createWebHistory(),
routes
});
Компонент монтируется с настоящим роутером:
const wrapper = mount(ComponentUnderTest, {
global: {
plugins: [router]
}
});
Навигация может быть смоделирована через router.push и
router.replace:
await router.push('/about');
await router.isReady();
expect(wrapper.html()).toContain('About');
Такой подход полезен, если компонент использует watch на route или navigation guards.
Проверка компонентов, зависящих от динамических параметров маршрута
(params) или query-параметров, требует настройки
$route:
const wrapper = mount(ComponentUnderTest, {
global: {
mocks: {
$route: {
params: { id: '123' },
query: { ref: 'abc' }
}
}
}
});
Пример использования внутри теста:
expect(wrapper.vm.$route.params.id).toBe('123');
expect(wrapper.vm.$route.query.ref).toBe('abc');
Для проверки того, что компонент инициирует переход, используется мок
push или replace:
const mockRouter = { push: jest.fn() };
const wrapper = mount(ComponentUnderTest, {
global: {
mocks: { $router: mockRouter }
}
});
wrapper.find('button.go-to-profile').trigger('click');
expect(mockRouter.push).toHaveBeenCalledWith({ name: 'Profile', params: { userId: 1 } });
Таким образом можно изолировать логику переходов, не выполняя реальные маршруты и не влияя на глобальное состояние приложения.
Если компонент использует guards типа beforeRouteEnter,
beforeRouteUpdate или beforeRouteLeave, их
можно протестировать через мок:
const mockNext = jest.fn();
ComponentUnderTest.beforeRouteEnter({ path: '/login' }, null, mockNext);
expect(mockNext).toHaveBeenCalled();
await router.isReady() при работе
с настоящим роутером в тестах, чтобы избежать ошибок из-за асинхронной
инициализации.$route, чтобы не зависеть от глобального состояния.Мок Vue Router в тестах позволяет изолировать компонент, контролировать навигацию и параметры маршрута, обеспечивая надёжное и предсказуемое поведение тестов.