Vue Test Utils v2无法Mock全局route函数的问题求助
全局route函数的正确Mock方案
先明确你的全局route函数是哪种注入方式,对应不同的Mock方法:
1. 函数挂载到Vue实例(app.config.globalProperties)
如果是在app.js里通过app.config.globalProperties.$route = route挂载到全局,测试时直接在组件挂载配置里用global.mocks模拟:
import { mount } from '@vue/test-utils' import ConversationStatus from './ConversationStatus.vue' import { vi } from 'vitest' describe('ConversationStatus', () => { it('调用全局route函数切换归档状态', () => { // 创建Mock函数,指定返回的路由地址 const mockRoute = vi.fn(() => '/mock-conversation/archive') const wrapper = mount(ConversationStatus, { global: { mocks: { $route: mockRoute // 这里的key要和你挂载的全局属性名完全一致,比如如果是直接挂载成route就写route } } }) // 触发组件的toggleArchive方法 wrapper.vm.toggleArchive() // 断言Mock函数被调用 expect(mockRoute).toHaveBeenCalled() // 若知道调用参数,可进一步验证:expect(mockRoute).toHaveBeenCalledWith('conversation.archive', { id: 1 }) }) })
2. 函数挂载到window对象
如果route是挂载在window上的全局函数(比如window.route = route),直接Mockwindow上的对应属性即可:
import { mount } from '@vue/test-utils' import ConversationStatus from './ConversationStatus.vue' import { vi } from 'vitest' describe('ConversationStatus', () => { it('调用window.route切换归档', () => { // 备份原函数,避免影响其他测试 const originalRoute = window.route // 替换成Mock函数 window.route = vi.fn(() => '/mock-url') const wrapper = mount(ConversationStatus) wrapper.vm.toggleArchive() expect(window.route).toHaveBeenCalled() // 测试结束后恢复原函数 window.route = originalRoute }) })
3. 组件直接import route模块
如果组件里是通过import route from '@/utils/route'引入的函数,用vi.mockMock整个模块:
import { vi } from 'vitest' // Mock目标模块,指定默认导出为Mock函数 vi.mock('@/utils/route', () => ({ default: vi.fn(() => '/mock-path') })) import route from '@/utils/route' import { mount } from '@vue/test-utils' import ConversationStatus from './ConversationStatus.vue' describe('ConversationStatus', () => { it('调用导入的route函数', () => { const wrapper = mount(ConversationStatus) wrapper.vm.toggleArchive() expect(route).toHaveBeenCalled() }) })
4. 若是Inertia.js的全局route函数
如果用的是Inertia的route辅助函数,同时要Mockrouter.visit的话:
import { vi } from 'vitest' // Mock Inertia的route模块 vi.mock('@inertiajs/vue3', () => ({ route: vi.fn(() => '/mock-archive') })) import { mount } from '@vue/test-utils' import ConversationStatus from './ConversationStatus.vue' describe('ConversationStatus', () => { it('触发route生成地址并调用router.visit', () => { const mockVisit = vi.fn() const wrapper = mount(ConversationStatus, { global: { mocks: { $inertia: { visit: mockVisit } } } }) wrapper.vm.toggleArchive() expect(route).toHaveBeenCalled() expect(mockVisit).toHaveBeenCalledWith('/mock-archive') }) })
常见问题排查
- 确保Mock的属性名和全局注入的名称完全一致(比如是
$route还是route) - 若用
vi.mock,模块路径要和组件里导入的路径完全匹配 - 测试后记得清理Mock(比如恢复window上的原函数),避免污染其他测试用例
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

