如何解决Vue.js3组合式API组件useRoute路由测试失败问题?
问题分析与解决方案
问题根源
你之前的Mock方式仅在全局挂载了route变量,但<script setup>中通过useRoute()获取的是Vue Router注入的路由实例,并非这个全局变量。第一个组件能生效是巧合:模板中的route.path在组件setup上下文的route变量(useRoute()返回的undefined)无法访问时,会 fallback 到全局Mock的route变量;而第二个组件的computed属性直接调用了setup中useRoute()返回的undefined对象,因此触发TypeError。
正确解决方案
方案1:Mock $route 注入变量(推荐,简单直接)
Vue Router会将路由实例以$route的形式注入组件,useRoute()本质是返回这个注入的实例。只需在测试中Mock$route即可:
let wrapper; beforeEach(() => { wrapper = mount(HelloWorld, { props: { msg: 'Hello!' }, global: { mocks: { $route: { path: '/hello' } } } }); });
此方案下,组件中useRoute()会直接返回Mock的$route对象,不管是模板直接使用还是computed属性中调用,都能正常获取path值。
方案2:Mock useRoute 函数(适合复杂场景)
如果需要更灵活控制useRoute()的返回值,可直接Mock该函数:
Mocha + Sinon 实现
import sinon from 'sinon'; import { useRoute } from 'vue-router'; import HelloWorld from '@/components/HelloWorld.vue'; import { mount } from '@vue/test-utils'; let useRouteStub; beforeEach(() => { // 创建Stub,返回模拟路由对象 useRouteStub = sinon.stub().returns({ path: '/hello' }); // 替换vue-router中的useRoute Object.defineProperty(require('vue-router'), 'useRoute', { value: useRouteStub }); wrapper = mount(HelloWorld, { props: { msg: 'Hello!' } }); }); afterEach(() => { // 恢复原函数,避免影响其他测试 useRouteStub.restore(); });
手动Mock(无需Sinon)
import { useRoute } from 'vue-router'; import HelloWorld from '@/components/HelloWorld.vue'; import { mount } from '@vue/test-utils'; const originalUseRoute = useRoute; beforeEach(() => { // 替换useRoute为自定义函数 useRoute = () => ({ path: '/hello' }); wrapper = mount(HelloWorld, { props: { msg: 'Hello!' } }); }); afterEach(() => { // 恢复原函数 useRoute = originalUseRoute; });
验证
使用上述任一方案后,第二个组件的computed属性path会正确读取到Mock的/hello路径,不再出现Cannot read properties of undefined错误。
内容的提问来源于stack exchange,提问作者Андрей Кондратов
相关产品推荐
相关产品推荐

