本文基于vue-webpack-boilerplate。官方推荐使用Karma+Mocha+Chai来进行单元测试。
介绍
Karma:一个测试运行器,用于启动浏览器,运行测试案例并将结果报告给我们。该工具的主要作用是将项目运行在各种主流Web浏览器进行测试。
Mocha:一个测试框架。可结合chai断言库使用。
Chai:一个测试断言库,提供了更好的断言语法。所谓断言,就是对组件做一些操作,并预言产生的结果。如果测试结果与断言相同则测试通过。Chai断言库中,to be been is that which and has have with at of same but does这些语言链是没有意义的,只是便于理解而已。
实践
组件无依赖,无props
对于无需导入任何依赖,也没有props的,直接编写测试案例即可。
MyComponent.vue
<template>
<span>{{ message }}</span>
</template>
<script>
export default {
data () {
return {
message: 'hello!'
}
},
created () {
this.message = 'bye!'
}
}
</script>
MyComponent.spec.js
// 导入 Vue.js 和组件,进行测试
import Vue from 'vue'
import MyComponent from 'path/to/MyComponent.vue'
describe('MyComponent', () => {
// 检查原始组件选项
it('has a created hook', () => {
expect(typeof MyComponent.created).to.eql('function')
})
})
组件有props
对于组件需要props,编写单元测试时,通过propsData
传递该参数。
MyComponent.vue
<template>
<p>{{ msg }}</p>
</template>
<script>
export default {
props: ['msg']
}
</script>
MyComponent.spec.js
import Vue from 'vue'
import MyComponent from 'path/to/MyComponent.vue'
function getRenderedText (Component, propsDataMsg) {
const Ctor = Vue.extend(Component)
const vm = new Ctor({ propsData: propsDataMsg}).$mount()
return vm.$el.textContent
}
describe('MyComponent', () => {
it('renders correctly with different props', () => {
expect(getRenderedText(MyComponent, {
msg: 'Hello'
})).to.eql('Hello')
expect(getRenderedText(MyComponent, {
msg: 'Bye'
})).to.eql('Bye')
})
})
组件有依赖
若组件存在依赖,则可通过inject-loader解决。inject-loader可将任意依赖项注入到*.vue组件中。
MyComponent.vue
<template>
<div class="msg">{{ msg }}</div>
</template>
<script>
// this dependency needs to be mocked
import SomeService from '../service'
export default {
data () {
return {
msg: SomeService.msg
}
}
}
</script>
MyComponent.spec.js
//“!!”表示禁用全局配置的所有loaders。“vue-loader?inject!”表示使用vue-loader,传入inject参数。
const ExampleInjector = require('!!vue-loader?inject!./example.vue')
//运行ExampleInjector函数返回一个MyComponent的实例,该实例中MyComponent组件的依赖项已被模拟。
const ExampleWithMocks = ExampleInjector({
// mock it
'../service': {
msg: 'Hello from a mocked service!'
}
})
describe('MyComponent', () => {
it('should render', () => {
const vm = new Vue({
template: '<div><test></test></div>',
components: {
'test': ExampleWithMocks
}
}).$mount()
expect(vm.$el.querySelector('.msg').textContent).to.eql('Hello from a mocked service!')
})
})
异步操作
对于异步操作,it块执行的时候,需要传入一个回调函数,通常该函数被命名为done。当测试结束的时候,必须显式调用这个函数,告诉Mocha测试结束了。否则,Mocha就无法知道,测试是否结束,会一直等到超时报错。
// 在状态更新后检查生成的 HTML
it('updates the rendered message when vm.message updates', done => {
const vm = new Vue(MyComponent).$mount()
vm.message = 'foo'
// 在状态改变后和断言 DOM 更新前等待一刻
Vue.nextTick(() => {
expect(vm.$el.textContent).to.eql('foo')
done()
})
})
npm run unit
执行 npm run unit 命令运行单元测试。会产生结果列表:
若想看测试覆盖率等情况,可在test/unit/coverage查看。
注意
测试脚本都放在 test/unit/specs/ 目录下。
脚本命名方式是[组件名].spec.js。
在karma.conf.js文件里修改karma配置。
单元测试默认测试 src 目录下除了 main.js 之外的所有文件,可在 test/unit/index.js 文件中修改。
-
测试脚本里面应该包括一个或多个describe块,每个describe块应该包括一个或多个it块。
describe块称为"测试套件"(test suite),表示一组相关的测试。它是一个函数,第一个参数是测试套件的名称("加法函数的测试"),第二个参数是一个实际执行的函数。
it块称为"测试用例"(test case),表示一个单独的测试,是测试的最小单位。它也是一个函数,第一个参数是测试用例的名称("1 加 1 应该等于 2"),第二个参数是一个实际执行的函数。
Mocha在describe块之中,提供测试用例的四个钩子:before()、after()、beforeEach()和afterEach()。它们会在指定时间执行。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。