项目:https://github.com/marioedgar/webpack-unit-test
我有一个使用vue CLI生成的Vue.js应用程序。我只是稍微编辑了HelloWorld组件以从我的测试服务中获取一些异步数据,你可以在这里看到:
<template>
<h1>{{ message }}</h1>
</template>
<script>
import service from './test.service'
export default {
name: 'HelloWorld',
created () {
service.getMessage().then(message => {
this.message = message
})
},
data () {
return {
message: 'A'
}
}
}
</script>
<style scoped>
</style>
&#13;
测试服务位于同一目录中,非常简单:
class Service {
getMessage () {
return new Promise((resolve, reject) => {
console.log('hello from test service')
resolve('B')
})
}
}
const service = new Service()
export default service
&#13;
因此,为了模拟这项服务,我使用webpack vue-loader注入模拟服务,如官方文档中所述:
https://vue-loader.vuejs.org/en/workflow/testing-with-mocks.html
所以这是我的测试,几乎与示例相同:
import Vue from 'vue'
const HelloInjector = require('!!vue-loader?inject!../../../src/components/HelloWorld')
const Hello = HelloInjector({
// mock it
'./test.service': {
getMessage () {
return new Promise((resolve, reject) => {
resolve('C')
})
}
}
})
describe('HelloWorld.vue', () => {
it('should render', () => {
const vm = new Vue({
template: '<div><test></test></div>',
components: {
'test': Hello
}
}).$mount()
expect(vm.$el.querySelector('h1').textContent).to.equal('C')
})
})
&#13;
我面临两个问题:
it('should render', (done) => {
const vm = new Vue({
template: '<div><test></test></div>',
components: {
'test': Hello
}
}).$mount()
Vue.nextTick(() => {
expect(vm.$el.querySelector('h1').textContent).to.equal('C')
done()
})
})
&#13;
然而,这不起作用,除非我嵌套3次nextTicks,这对我来说似乎非常讨厌。有什么我想让这个工作吗?这个例子看起来非常简单,但是如果没有很多nextTicks,我就无法通过这个测试
[vue warn]无法安装组件:未定义模板或渲染功能
同样,这有时只会发生。我可以在没有任何更改的情况下运行相同的单元测试,并且它会在50%的时间向我显示此消息。
答案 0 :(得分:2)
我真的无法弄清楚为什么有时组件无法安装。我甚至不确定它是否与注射器有关,但无论如何,我通过不使用它来保持测试的一致性;尝试不同的方法。
如果通过props
注入服务而不是直接使用该服务,则该组件可能更具可测试性。
<template>
<div>
<h1>{{ message }}</h1>
</div>
</template>
<script>
import service from './test.service'
export default {
name: 'HelloWorld',
created () {
this.service.getMessage().then(message => {
this.message = message
})
},
data () {
return {
message: 'A'
}
},
props: {
service: {
default: service
}
}
}
</script>
<style scoped>
</style>
这使得注入器变得不必要,因为可以使用构造函数中的propsData
将模拟的服务传递给组件。
import Vue from 'vue'
import Async from '@/components/Async'
const service = {
getMessage () {
return new Promise((resolve, reject) => {
resolve('C')
})
}
}
describe('Async.vue', () => {
let vm
before(() => {
const Constructor = Vue.extend(Async)
vm = new Constructor({
propsData: {
service: service
}
}).$mount()
})
it('should render', function () {
// Wrapping the tick inside a promise, bypassing PhantomJS's lack of support
return (new Promise(resolve => Vue.nextTick(() => resolve()))).then(() => {
expect(vm.$el.querySelector('h1').textContent).to.equal('C')
})
})
})