以前也沒有去接觸過前端的單元測試,也是這幾天開始瞭解,開始並無頭緒,因此就在網上以及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('初始值') }) 複製代碼
這個時候運行的話會報錯誤