如何编写在vue组件中模拟$ route对象的测试

Jer*_*ang 24 unit-testing sinon vue-component vue-loader vuejs2

我有一个包含类似语句成分this.$route.fullPath,我应该怎么嘲笑的值fullPath$route对象,如果我想测试组件?

SCo*_*vin 32

最好不要模拟vue-router,而是使用它来渲染组件,这样你就可以得到一个正常工作的路由器.例:

import Vue from 'vue'
import VueRouter from 'vue-router'
import totest from 'src/components/totest'

describe('totest.vue', () => {
  it('should totest renders stuff', done => {
    Vue.use(VueRouter)
    const router = new VueRouter({routes: [
        {path: '/totest/:id', name: 'totest', component: totest},
        {path: '/wherever', name: 'another_component', component: {render: h => '-'}},
    ]})
    const vm = new Vue({
      el: document.createElement('div'),
      router: router,
      render: h => h('router-view')
    })
    router.push({name: 'totest', params: {id: 123}})
    Vue.nextTick(() => {
      console.log('html:', vm.$el)
      expect(vm.$el.querySelector('h2').textContent).to.equal('Fred Bloggs')
      done()
    })
  })
})
Run Code Online (Sandbox Code Playgroud)

注意事项:

  1. 我正在使用仅运行时版本的vue render: h => h('router-view').
  2. 我只测试totest组件,但如果它们被totest例如引用,则可能需要其他组件.another_component在这个例子中.
  3. 您需要nextTick先渲染HTML才能查看/测试它.

其中一个问题是我发现的大多数示例都提到了旧版本vue-router,请参阅迁移文档,例如.一些使用router.go()现在不起作用的例子.

  • 我不同意您不应该嘲笑Vue Router。见我的答案— /sf/answers/3123355581/ (2认同)

Edd*_*Edd 27

我不同意最好的答案 - 你可以$route毫无问题地嘲笑.

另一方面,在基础构造函数上多次安装vue-router 导致问题.它添加$route$router作为只读属性.这使得在将来的测试中无法覆盖它们.

使用vue-test-utils有两种方法可以实现这一点.

mocks选项模拟vue-router

const $route = {
    fullPath: 'full/path'
}
const wrapper = mount(ComponentWithRouter, { 
  mocks: {
    $route
  } 
})

wrapper.vm.$route.fullPath // 'full/path'
Run Code Online (Sandbox Code Playgroud)

您还可以使用createLocalVue安全地安装Vue Router:

使用createLocalVue在测试中安全地安装vue-router

const localVue = createLocalVue()
localVue.use(VueRouter)
const routes = [
 {
   path: '/',
   component: Component
 }
]
const router = new VueRouter({
 routes
})
const wrapper = mount(ComponentWithRouter, { localVue, router })
expect(wrapper.vm.$route).to.be.an('object')
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是,vue-cli在router/index.js中删除了一个`Vue.use(Router)`,它被加载到全局Vue中.如果您说组件中有一个`router.push`调用,它会在测试之前导入该全局只读$ router(因此无法模拟). (2认同)

Ily*_*rim 5

没有答案帮助我,所以我深入研究vue-test-utils文档并找到了一个可行的答案,所以你需要导入。

import { shallowMount,createLocalVue } from '@vue/test-utils';
import router from '@/router.ts';
const localVue = createLocalVue();
Run Code Online (Sandbox Code Playgroud)

我们创建了一个示例vue实例。在测试时您需要使用,shallowMount以便您可以提供vue应用程序实例和路由器。

describe('Components', () => {
  it('renders a comment form', () => {
    const COMMENTFORM = shallowMount(CommentForm,{
      localVue,
      router
    });
  })
})
Run Code Online (Sandbox Code Playgroud)

您可以轻松地通过路由器和浅安装,它不会给您错误。如果你想通过你使用的商店:

import { shallowMount,createLocalVue } from '@vue/test-utils';
import router from '@/router.ts';
import store from '@/store.ts';
const localVue = createLocalVue();
Run Code Online (Sandbox Code Playgroud)

然后通过商店:

describe('Components', () => {
  it('renders a comment form', () => {
    const COMMENTFORM = shallowMount(CommentForm,{
      localVue,
      router,
      store
    });
  })
})
Run Code Online (Sandbox Code Playgroud)

此解决方案解决了以下错误:

  • 使用时无法读取未定义的属性“参数” this.$route.params.id
  • 未知的自定义元素 router-link

?