Vue单元测试---Karma+Mocha+Chai实践
本文基于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()。它们会在指定时间执行。