以前也没有去接触过前端的单元测试,也是这几天开始了解,开始并无头绪,因此就在网上以及github上去看了一些以前比较流行的测试框架。发现比较流行的是karma + mocha + Chrome的组合。当我单独一个个去看的时候,发现其内容仍是比较的多的。以后选取了jest也是通过对比权衡的javascript
在使用 Jest 以前,我须要一个测试框架(mocha),须要一个测试运行器(karma),须要一个断言库(chai),须要一个用来作 spies/stubs/mocks 的工具(sinon 以及 sinon-chai 插件),一个用于测试的浏览器环境(能够是 Chrome 浏览器,也能够用 PhantomJS)。 而使用 Jest 后,只要安装它,全都搞定了。前端
Jest 的官方文档很完善,对着文档很快就能上手。而在以前,我须要学习好几个插件的用法,至少得知道 mocha 用处和原理吧 我得学会 karma 的配置和命令,chai 的各类断言方法……,常常得周旋于不一样的文档站之间,实际上是件很烦也很低效的事vue
jsdom 的一些局限性:由于 Jest 是基于 jsdom 的,jsdom 毕竟不是真实的浏览器环境,它在测试过程当中其实并不真正的“渲染”组件。这会致使一些问题,例如,若是组件代码中有一些根据实际渲染后的属性值进行计算(好比元素的 clientWidth)就可能出问题,由于 jsdom 中这些参数一般默认是 0.java
综上所述,最终我肯定下来的方案是使用成熟好用的测试工具库 --- vue-test-utils 其前身是 avoriaz,avoriaz 也是一个不错的包,但其 README 中有说明,当 vue-test-utils 正式发布的时候, 它将会被废弃。 vue-test-utils 能极大地简化 Vue.js 单元测试。 例如:Vue 单元测试,通常是像下面这样的(包括 vue-cli 提供的模板里默认也是这样):webpack
import Vue from 'vue' import HelloWorld from '@/components/HelloWorld' describe('HelloWorld.vue', () => { it('should render correct contents', () => { const Constructor = Vue.extend(HelloWorld) const vm = new Constructor().$mount() expect(vm.$el.querySelector('.hello h1').textContent) .toEqual('Welcome to Your Vue.js App') }) }) 复制代码
使用 vue-test-utils 后,你能够像下面这样ios
import { shallow } from '@vue/test-utils' import HelloWorld from '@/components/HelloWorld' describe('HelloWorld.vue', () => { it('should render correct contents', () => { const wrapper = shallow(HelloWorld, { attachToDocument: ture }) expect(wrapper.find('.hello h1').text()).to.equal('Welcome to Your Vue.js App') }) }) 复制代码
能够看到代码更加简洁了。wrapper 内含许多有用的方法,上面的例子中所使用的 find() 其中最简单不过的一个。vue-test-utils 还有 createLocalVue() 等方法以及 stub 之类的功能,基本上能够完成绝大部分状况下的测试用例,这也是很是的实用的了。git
安装使用的方式很简单,因为想引入到现有的项目中来,现有的项目大可能是vue-cli建立的,因此一开始的时候基本上是已经安装并配置好了 webpack、vue-loader 和 Babel。若是是比较原始的项目,也是能够单独安装的。github
$ npm install --save-dev jest @vue/test-utils
复制代码
// package.json { "scripts": { "test": "jest" } } 复制代码
npm install --save-dev vue-jest
复制代码
{ // ... "jest": { "moduleFileExtensions": [ "js", "json", // 告诉 Jest 处理 `*.vue` 文件 "vue" ], "transform": { // 用 `vue-jest` 处理 `*.vue` 文件 ".*\\.(vue)$": "vue-jest" } } } 复制代码
此处我根据本身的需求来进行整理web
// viewTest.vue
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>1212121</p>
</div>
</template>
<script>
export default {
name: 'viewTest',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
}
}
复制代码
// viewTest.spec import { mount } from '@vue/test-utils' import Component from '../../../src/components/viewTest' describe('页面展现测试', () => { test('检查元素是否存在', () => { const wrapper = mount(Component) expect(wrapper.contains('.hello h1')).toBe(true) console.log(wrapper.find('.hello h1').text()) expect(wrapper.text()).toContain('Welcome') }) }) 复制代码
这个是最简单的对页面的dom节点的测试,以及能够对文案进行一些测试,这些是比较基础的vue-cli
// event.vue
<template>
<div>
<h1>My To Do event</h1>
<h2>wawawawawawa</h2>
<input v-model="newItem">
<button @click="addItemToList">Add</button>
</br>
<!--displays event -->
<ul>
<li v-for="item in listItems">{{ item }}</li>
</ul>
</div>
</template>
<script>
export default {
name: 'event',
data () {
return {
listItems: ['buy food', 'play games', 'sleep'],
newItem: ''
}
},
methods: {
addItemToList() {
this.listItems.push(this.newItem);
this.newItem = '';
}
}
}
</script>
复制代码
// event.spec.js // 从测试实用工具集中导入 `mount()` 方法 // 同时导入你要测试的组件 import { mount } from '@vue/test-utils' import Component from '../../../src/components/itemEvent' describe('事件触发测试', () => { test('事件触发测试', () => { // 如今挂载组件,你便获得了这个包裹器 const wrapper = mount(Component) const button = wrapper.find('button') wrapper.setData({ newItem: '添加测试项', }) button.trigger('click') console.log(wrapper.text()) expect(wrapper.text()).toContain('添加测试项') }) }) 复制代码
这里是在模拟用户交互的一个测试,当用户点击按钮的时候会把数据插入到当前的列表中来,因此最开始须要定位到这个按钮,能够用find(),以后要去触发这个事件, button.trigger('click'),而后把预期的结果,与按照流程的结果相比较,以达到测试的效果。这里模拟的是一个点击事件,固然,api也支持各类的鼠标事件以及键盘事件。
// axios.js export default { get: () => Promise.resolve({ data: 'response' }) } 复制代码
<template>
<div>
<button @click="fetchResults">发送请求</button>
{{value}}
</div>
</template>
<script>
import axios from '../axios.js'
export default {
data () {
return {
value: '初始值'
}
},
methods: {
async fetchResults () {
const response = await axios.get('mock/service')
this.value = response.data
console.log(this.value)
}
},
created (){
console.log(axios.get)
}
}
</script>
复制代码
// async.spec.js import { shallowMount } from '@vue/test-utils' import async from '../../../src/components/async' jest.mock('axios') it('当点击按钮发送请求时检验返回值', () => { const wrapper = shallowMount(async) console.log(jest) wrapper.find('button').trigger('click') // expect(wrapper.value) expect(wrapper.vm.value).toBe('response') // console.log(wrapper.vm.value).toBe('初始值') }) 复制代码
这个时候运行的话会报错误