Vue Router 测试前置守卫需用 createMemoryHistory 模拟导航,mock 异步依赖后 await router.isReady(),再断言 currentRoute.value.path 验证跳转、重定向或拦截行为。

在 Vue Router 中测试路由前置守卫(beforeEach)对异步跳转的拦截逻辑,核心是模拟导航行为、控制守卫内部的异步流程(如权限检查、token 验证),并验证守卫是否按预期调用 next()、next(false)、next('/login') 等响应。
使用 Vue Router 的 createRouter + createMemoryHistory 搭建可测试环境
避免依赖浏览器真实 history,用内存历史模式让测试可控:
- 安装
@vue/test-utils和vitest(或 Jest) - 创建一个最小化 router 实例,注册你的守卫
- 用
createMemoryHistory()初始化,便于手动触发导航和断言当前路由
手动触发导航并等待守卫执行完成
Vue Router 的前置守卫是异步的,需确保测试等待其“真正结束”。关键点:
- 调用
router.push('/target')后,必须 await router.isReady()(Vue Router 4+ 推荐),或监听router.beforeEach返回的 Promise(若守卫返回 Promise) - 若守卫内有
await api.checkAuth(),可在测试中 mock 该 API 并控制 resolve/reject - 例如:
vi.mock('@/api/auth', () => ({ checkAuth: vi.fn().mockResolvedValue(true) }))
断言守卫行为:跳转是否被阻止、重定向是否正确
通过检查 router.currentRoute.value 的路径、查询参数、匹配的 record 来验证结果:
立即学习“Java免费学习笔记(深入)”;
-
expect(router.currentRoute.value.path).toBe('/login')→ 检查是否重定向 -
expect(router.currentRoute.value.path).toBe('/dashboard')→ 检查是否放行 - 若守卫调用
next(false),当前路由应保持不变(可用router.push前后对比fullPath) - 注意:调用
next()无参时,导航会继续;但若守卫没调用next任何参数,导航会挂起——测试中可通过超时断言发现(如expect(...).rejects.toThrow())
覆盖典型异步场景的测试用例
每个用例应独立 mock 异步依赖,并明确验证守卫响应:
-
有权限 → 正常跳转:mock API 返回
{ ok: true },断言目标路由生效 -
无权限 → 重定向登录页:mock 返回
{ ok: false },断言path === '/login'且含redirect查询参数 -
网络失败 → 跳转到错误页或 fallback:mock
checkAuthreject,断言跳转至/error或调用next('/error') -
守卫未调用 next → 导航卡住:不调用
next,断言router.isReady()永不 resolve(需设 timeout)



















