本文基於vue-webpack-boilerplate。官方推薦使用Karma+Mocha+Chai來進行單元測試。html
Karma:一個測試運行器,用於啓動瀏覽器,運行測試案例並將結果報告給咱們。該工具的主要做用是將項目運行在各類主流Web瀏覽器進行測試。vue
Mocha:一個測試框架。可結合chai斷言庫使用。webpack
Chai:一個測試斷言庫,提供了更好的斷言語法。所謂斷言,就是對組件作一些操做,並預言產生的結果。若是測試結果與斷言相同則測試經過。Chai斷言庫中,to be been is that which and has have with at of same but does這些語言鏈是沒有意義的,只是便於理解而已。git
對於無需導入任何依賴,也沒有props的,直接編寫測試案例便可。npm
MyComponent.vueapi
<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,編寫單元測試時,經過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 命令運行單元測試。會產生結果列表:
若想看測試覆蓋率等狀況,可在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()。它們會在指定時間執行。