Vitest中Mock Vue Router测试router-link跳转触发失败问题
解决Vue3+Vitest中Mock Router后router-link点击未触发路由方法的问题
问题分析
你遇到的AssertionError: expected "spy" to be called at least once,核心原因是路由Mock未正确注入或RouterLink组件未被正确处理,导致点击事件没有触发预期的router.push调用。以下是两种可行的解决方案:
方案1:手动Mock vue-router(轻量方案)
直接MockuseRouter和RouterLink组件,确保路由逻辑能被正确触发:
import { mount } from '@vue/test-utils' import { vi } from 'vitest' import TestView from './TestView.vue' import { useRouter } from 'vue-router' // Mock vue-router核心模块 vi.mock('vue-router', () => ({ // Mock useRouter钩子 useRouter: vi.fn(), // Mock RouterLink组件为简单a标签,避免依赖真实路由实例 RouterLink: { template: '<a><slot /></a>', props: ['to'] } })) test('点击router-link触发router.push', async () => { // 创建push方法的Spy const mockPush = vi.fn() // 让useRouter返回包含push方法的对象 useRouter.mockReturnValue({ push: mockPush }) // 挂载组件 const wrapper = mount(TestView) // 触发点击事件(await等待异步逻辑完成) await wrapper.find('[data-test="test-link"]').trigger('click') // 断言push方法被正确调用 expect(mockPush).toHaveBeenCalledWith('login') })
方案2:使用官方vue-router-mock工具(推荐)
Vue Test Utils提供了专门的vue-router-mock包,能更完整地模拟路由环境,无需手动Mock RouterLink:
首先确保安装依赖:
npm install vue-router-mock --save-dev
然后编写测试:
import { mount } from '@vue/test-utils' import { createRouterMock, injectRouterMock } from 'vue-router-mock' import TestView from './TestView.vue' import { vi } from 'vitest' test('点击router-link触发路由跳转', async () => { // 创建路由Mock实例,可自定义路由规则 const router = createRouterMock({ routes: [ { path: '/login', name: 'login' } ] }) // 将路由Mock注入测试上下文 injectRouterMock(router) // 挂载组件时注入路由Mock const wrapper = mount(TestView, { global: { plugins: [router] } }) // 触发点击事件 await wrapper.find('[data-test="test-link"]').trigger('click') // 断言路由push方法被调用 expect(router.push).toHaveBeenCalledWith('login') })
常见问题排查
- 未Mock RouterLink组件:原生RouterLink依赖注入的路由实例,若未Mock,点击事件会走默认a标签跳转逻辑,不会触发
router.push。 - useRouter Mock返回值错误:确保
useRouter返回的对象包含push方法的Spy,而非空对象或普通函数。 - 未等待异步逻辑:
trigger('click')是异步操作,必须用await等待事件处理完成后再断言。
内容的提问来源于stack exchange,提问作者Davidhdm
相关产品推荐
相关产品推荐

