Unit testing 如何编写模拟vue组件中$route对象的测试
我有一个包含如下语句的组件:Unit testing 如何编写模拟vue组件中$route对象的测试,unit-testing,sinon,vue-component,vuejs2,vue-loader,Unit Testing,Sinon,Vue Component,Vuejs2,Vue Loader,我有一个包含如下语句的组件:this.$route.fullPath,如果我想测试该组件,我应该如何模拟$route对象的fullPath的值?最好不要模拟vue router,而是使用它来渲染该组件,这样你就可以得到一个正常工作的路由器。例如: 从“Vue”导入Vue 从“vue路由器”导入VueRouter 从“src/components/totest”导入totest 描述('totest.vue',()=>{ 它('should totest renders stuff',done=>
this.$route.fullPath
,如果我想测试该组件,我应该如何模拟$route
对象的fullPath
的值?最好不要模拟vue router
,而是使用它来渲染该组件,这样你就可以得到一个正常工作的路由器。例如:
从“Vue”导入Vue
从“vue路由器”导入VueRouter
从“src/components/totest”导入totest
描述('totest.vue',()=>{
它('should totest renders stuff',done=>{
Vue.use(VueRouter)
const router=new VueRouter({路由:[
{path:'/totest/:id',name:'totest',component:totest},
{path:'/where',name:'other_component',component:{render:h=>'-'},
]})
const vm=新的Vue({
el:document.createElement('div'),
路由器:路由器,,
render:h=>h('router-view')
})
push({name:'totest',params:{id:123}})
Vue.nextTick(()=>{
log('html:',vm.$el)
expect(vm.$el.querySelector('h2').textContent).to.equal('Fred Bloggs'))
完成()
})
})
})
注意事项:
render:h=>h('router-view')
totest
组件,但是如果totest
引用了其他组件,则可能需要其他组件,例如本例中的另一个组件
nextTick
,才能呈现HTML其中一个问题是,我发现的大多数示例都提到了旧版本的
vue路由器
,请参见,例如,一些示例使用了router.go()
,但现在不起作用。感谢@SColvin的回答;在我的场景中帮助找到了答案,其中我有一个带有路由器链接的组件正在抛出
ERROR: '[Vue warn]: Error in render function: (found in <RouterLink>)'
到
不需要将参数传递到视图中,我可以将组件简化为默认渲染,无需推送,也无需等待下一步。还有其他人 我不同意上面的答案-你可以毫无疑问地模仿
$route
另一方面,在基本构造函数上多次安装vue路由器将导致出现问题。它将$route
和$router
添加为只读属性。这使得在将来的测试中不可能覆盖它们
有两种方法可以实现这一点
用
const$route={
完整路径:“完整/路径”
}
const wrapper=mount(ComponentWithRouter,{
模拟:{
$route
}
})
wrapper.vm.$route.fullPath/'full/path'
您还可以使用createLocalVue安全地安装Vue路由器:
在测试中使用安全安装vue路由器
const localVue=createLocalVue()
localVue.use(VueRouter)
常数路由=[
{
路径:“/”,
组件:组件
}
]
常量路由器=新的VueRouter({
路线
})
const wrapper=mount(ComponentWithRouter,{localVue,router})
expect(wrapper.vm.route).to.be.an('对象')
除了@SColvin的精彩答案之外,下面是一个使用以下方法的示例:
我相信这也可以用。看看这个使用vue test utils的示例,我在这里模拟路由器和存储
import ArticleDetails from '@/components/ArticleDetails'
import { mount } from 'vue-test-utils'
import router from '@/router'
describe('ArticleDetails.vue', () => {
it('should display post details', () => {
const POST_MESSAGE = 'Header of our content!'
const EXAMPLE_POST = {
title: 'Title',
date: '6 May 2016',
content: `# ${POST_MESSAGE}`
}
const wrapper = mount(ArticleDetails, {
router,
mocks: {
$store: {
getters: {
getPostById () {
return EXAMPLE_POST
}
}
}
}
})
expect(wrapper.vm.$el.querySelector('h1.post-title').textContent.trim()).to.equal(EXAMPLE_POST.title)
expect(wrapper.vm.$el.querySelector('time').textContent.trim()).to.equal(EXAMPLE_POST.date)
expect(wrapper.vm.$el.querySelector('.post-content').innerHTML.trim()).to.equal(
`<h1>${POST_MESSAGE}</h1>`
)
})
})
从“@/components/ArticleDetails”导入ArticleDetails
从“vue测试utils”导入{mount}
从“@/router”导入路由器
描述('ArticleDetails.vue',()=>{
它('应显示帖子详细信息',()=>{
const POST_MESSAGE='我们内容的标题!'
const示例_POST={
标题:“标题”,
日期:“2016年5月6日”,
内容:`${POST#u MESSAGE}`
}
const wrapper=mount(ArticleDetails{
路由器,
模拟:{
$store:{
吸气剂:{
getPostById(){
返回示例\u POST
}
}
}
}
})
expect(wrapper.vm.$el.querySelector('h1.post title').textContent.trim())to.equal(例如_post.title)
expect(wrapper.vm.$el.querySelector('time').textContent.trim())到.equal(例如_POST.date)
expect(wrapper.vm.$el.querySelector('.post-content').innerHTML.trim()).to.equal(
`${POST_MESSAGE}`
)
})
})
这就是我一直在做的:
通过设置vm.\u routerRoot.\u router 比如说
var Constructor = Vue.extend(Your_Component)
var vm = new Constructor().$mount()
var your_mock_router = {hello:'there'}
vm.$router = your_mock_router //An error 'setting a property that has only a getter'
vm._routerRoot._router = your_mock_router //Wow, it works!
您可以在这里仔细检查他们的源代码:我发现的最简单的方法是模拟$route
it('renders $router.name', () => {
const $route = {
name: 'test name - avoriaz'
}
const wrapper = shallow(Component, {
mocks: {
$route
}
})
expect(wrapper.text()).to.equal($route.name)
})
我发现最简单的方法是使用localVue
import { createLocalVue, mount } from '@vue/test-utils'
import ComponentName from 'componentPath'
import Vuex from 'vuex'
import store from '@/store/store' //Add store file if any getters is accessed
import VueRouter from 'vue-router'
describe('File name', () => {
const localVue = createLocalVue()
localVue.use(VueRouter)
const routes = [ //Can also be rreplaced with route(router.js) file
{
path: '/path',
component: ComponentName,
name: 'Route name'
}
]
const router = new VueRouter({
routes
})
router.push({
name: 'Route name',
params: {}
}) //if needed
const wrapper = mount(ComponentName, {localVue, router, store })
beforeEach(function() {
});
it('Method()', () => {
wrapper.vm.methodName()
expect(wrapper.vm.$route.path).toBe(routes[0].path)
});
});
希望对你有帮助 没有答案对我有帮助,所以我深入研究了
vue test utils
文档,找到了一个可行的答案,所以您需要导入
import { shallowMount,createLocalVue } from '@vue/test-utils';
import router from '@/router.ts';
const localVue = createLocalVue();
我们创建了一个示例vue
实例。测试时,您需要使用shallowMount
,以便提供vue
应用程序实例和路由器
describe('Components', () => {
it('renders a comment form', () => {
const COMMENTFORM = shallowMount(CommentForm,{
localVue,
router
});
})
})
您可以很容易地通过路由器和浅装,它不会给您错误。如果您想通过门店,请使用:
import { shallowMount,createLocalVue } from '@vue/test-utils';
import router from '@/router.ts';
import store from '@/store.ts';
const localVue = createLocalVue();
然后通过商店:
describe('Components', () => {
it('renders a comment form', () => {
const COMMENTFORM = shallowMount(CommentForm,{
localVue,
router,
store
});
})
})
此解决方案解决了以下错误:
- 使用
this.$route.params.id
- 未知自定义元素
路由器链接
✔ 您不必专门“模拟”路由器。您的应用程序可以在全局vue范围内设置VueRouter,您仍然可以让它在测试中执行您想要的操作,而不会出现问题 使用
VueRouter
阅读localVue用法:
我目前正在从我们的主应用程序中引入一个复杂的路由器,并且能够调用jest.spyOn()
调用router.push()
,并在创建组件之前设置路径,运行shallowMount()
在created()
钩子中进行一些路由处理
解决方法
//萨姆威科
import { shallowMount,createLocalVue } from '@vue/test-utils';
import router from '@/router.ts';
const localVue = createLocalVue();
describe('Components', () => {
it('renders a comment form', () => {
const COMMENTFORM = shallowMount(CommentForm,{
localVue,
router
});
})
})
import { shallowMount,createLocalVue } from '@vue/test-utils';
import router from '@/router.ts';
import store from '@/store.ts';
const localVue = createLocalVue();
describe('Components', () => {
it('renders a comment form', () => {
const COMMENTFORM = shallowMount(CommentForm,{
localVue,
router,
store
});
})
})
<template>
... something
</template>
<script>
...
data () {
return {
authenticated: false
}
},
...
created () {
if(!this.authenticated && this.$route.path !== '/'){
this.$router.push('/')
}
}
</script>
import Vuex from 'vuex'
import VueRouter from 'vue-router'
import { shallowMount, createLocalVue } from '@vue/test-utils'
import SomeVueComponent from 'MyApp/components/someVueComponent'
import MyAppRouter from 'MyApp/router'
import MyAppCreateStore from 'MyApp/createStore'
import merge from 'lodash.merge'
function setVueUseValues (localVue) {
localVue.use(Vuex)
localVue.use(VueRouter)
// other things here like custom directives, etc
}
beforeEach(() => {
// reset your localVue reference before each test if you need something reset like a custom directive, etc
localVue = createLocalVue()
setVueUseValues(localVue)
})
let localVue = createLocalVue()
setVueUseValues(localVue)
test('my app does not react to path because its default is "/"', () => {
const options = {
localVue,
router: MyAppRouter,
store: MyAppCreateStore()
}
const routerPushSpy = jest.spyOn(options.router, 'push')
const wrapper = shallowMount(SomeVueComponent, options)
expect(routerPushSpy).toHaveBeenCalledTimes(0)
})
test('my app reacts to path because its not "/" and were not authenticated', () => {
const options = {
localVue,
router: MyAppRouter,
store: MyAppCreateStore()
}
const routerPushSpy = jest.spyOn(options.router, 'push')
options.router.push('/nothomepath')
expect(routerPushSpy).toHaveBeenCalledWith('/nothomepath') // <- SomeVueComponent created hook will have $route === '/nothomepath' as well as fullPath
const wrapper = shallowMount(SomeVueComponent, options)
expect(routerPushSpy).toHaveBeenCalledWith('/') // <- works
})
let routerPushSpy = jest.spyOn(wrapper.vm.$router, 'push') // or before hooks, etc
import { shallowMount } from '@vue/test-utils'
const $route = {
path: '/some/path'
}
const wrapper = shallowMount(Component, {
mocks: {
$route
}
})
wrapper.vm.$route.path // /some/path
...
mocks: {
$route: {fullPath: ''}
},
...