書接上文摩梧,karma+webpack搭建vue單元測試環(huán)境介紹了vue單元測試環(huán)境搭建及查看源文件的測試覆蓋覆蓋率。今天來說一下vue單元測試思路和case的寫法宣旱。測試框架使用jasmine仅父,語法參考。
代碼地址:https://github.com/MarxJiao/vue-karma-test/tree/spec-demo
測試關(guān)注點
對于vue組件浑吟,單元測試測試主要關(guān)注以下幾點:
- vue組件加載后笙纤,各數(shù)據(jù)模型是否符合預(yù)期
- 定義的方法是否可用
- filter是否可用
- 帶有props的組件,數(shù)據(jù)能否正常傳遞
- 異步更新DOM的情況
組件加載后的狀態(tài)
要測試組件加載后的狀態(tài)组力,首先我們需要將vue組件生成實例省容。并檢測掛載后實例的數(shù)據(jù)狀態(tài)。下面是個示例:
我們來看下src/app.vue
組件的代碼:
<template>
<div>
<h1>{{title}}</h1>
<vc-message :message="message"></vc-message>
</div>
</template>
<script>
import child from './components/child.vue'
export default {
data() {
return {
title: '標(biāo)題',
message: '這是子組件'
}
},
components: {
'vc-message': child
},
mounted() {
this.title = 'Hello world'
},
methods: {
setMessage(msg) {
this.message = msg;
}
}
}
</script>
組件加載后title的值應(yīng)該變成'Hello world'忿项,所以我們這樣來寫測試代碼
// 引用vue
import Vue from 'vue';
// 引用要測試的組件
import app from '../../src/app.vue';
// 描述要測試的內(nèi)容
describe('test app.vue', () => {
// 描述要測試的最小單元
it('組件加載后蓉冈,title應(yīng)該是Holle world', () => {
// 這里將app生成vue實例,并使用 $mount() 模擬掛載狀態(tài)
let vm = new Vue(app).$mount();
// 斷言組件的title是否變?yōu)榱?Hello world'
expect(vm.title).toEqual('Hello world');
});
});
執(zhí)行karma start
我們能看到測試通過轩触。
測試組件里面的方法
我們知道vue將data和methods都掛在了vue實例的根節(jié)點下寞酿,所以測試vue組件中的方法也和上面測試狀態(tài)一樣,直接調(diào)用vm的方法就行了脱柱。我們來測試以下setMessage
方法:
// 引用vue
import Vue from 'vue';
// 引用要測試的組件
import app from '../../src/app.vue';
// 描述要測試的內(nèi)容
describe('test app.vue', () => {
// 描述要測試的最小單元
it('設(shè)置message為『你好世界』', () => {
// 這里將app生成vue實例伐弹,并使用 $mount() 模擬掛載狀態(tài)
let vm = new Vue(app).$mount();
// 執(zhí)行setMessage方法
vm.setMessage('你好世界');
// 斷言組件的message是否變?yōu)榱?你好世界'
expect(vm.message).toEqual('你好世界');
});
});
執(zhí)行karma start
,就會看到測試成功榨为。如果剛才沒有關(guān)閉karma的話惨好,在watch模式下,測試會自動進行随闺。
怎么樣日川?有沒有感覺vue單元測試非常簡單,趕緊做起來吧矩乐。
filter測試
filter的測試就更簡單了龄句。filter就是純函數(shù),有固定的輸入輸出散罕,我們只需要執(zhí)行函數(shù)看預(yù)期結(jié)果就好了分歇。我們?yōu)榻M件添加一個轉(zhuǎn)換大寫的filter:
<template>
...
<h1>{{title | upperCase}}</h1>
...
</template>
<script>
...
filters: {
upperCase(str) {
return str.toUpperCase();
}
}
...
</script>
測試這個filter
// 引用要測試的組件
import app from '../../src/app.vue';
// 描述要測試的內(nèi)容
describe('test app.vue', () => {
it('upperCase過濾器能把app轉(zhuǎn)換為APP', () => {
// vue 組件export出來的是個對象,我們直接用這個對象的屬性和方發(fā)就能調(diào)用到要測試的filter
let appStr = app.filters.upperCase('app');
// 斷言組件的appStr是為'APP'
expect(appStr).toEqual('APP');
});
})
props測試
props依賴父組件欧漱,這個怎么測試呢职抡。我們來看下vue官方提供的方法
使用Vue.extend()將組件掛載Vue構(gòu)造器上,用propsData加入props數(shù)據(jù)误甚,之后new一個Vue實例缚甩,這樣就生成了一個獨立的帶props的vm和前面的實例一樣谱净,可以進行各種測試。
我們的child組件:
<template>
<div>
<div>{{message}}</div>
</div>
</template>
<script>
export default {
props: ['message']
}
</script>
測試child組件
// 引用vue
import Vue from 'vue';
// 引用要測試的組件
import child from '../../src/components/child.vue';
/**
* 獲取生成的vm
*
* @param {Object} Component 組件
* @param {Object} propsData props數(shù)據(jù)
* @return {Object} vue實例
*/
function getRenderedVm (Component, propsData) {
const Ctor = Vue.extend(Component)
const vm = new Ctor({ propsData }).$mount()
return vm
}
// 描述要測試的內(nèi)容
describe('test child.vue', () => {
// 描述要測試的最小單元
it('組件加載后蹄胰,child組件的message應(yīng)該是「這是子組件」', () => {
let childvm = getRenderedVm(child, {
message: '這是message'
});
// 斷言組件的child組件的props是否生效
expect(childvm.message).toEqual('這是message');
});
});
是不是so easy.
異步更新DOM的情況
異步更新DOM的情況岳遥,參考vue官網(wǎng)的示例
使用Vue.nextTick
來查看異步數(shù)據(jù)更新后dom是否變化
// 引用vue
import Vue from 'vue';
// 引用要測試的組件
import app from '../../src/app.vue';
// 描述要測試的內(nèi)容
describe('test app.vue', () => {
// 異步數(shù)據(jù)更新
it('數(shù)據(jù)更新后,視圖應(yīng)該改變', done => {
// 這里將app生成vue實例裕寨,并使用 $mount() 模擬掛載狀態(tài)
let vm = new Vue(app).$mount();
// 掛載后改變title
vm.title = 'APP';
Vue.nextTick(() => {
let title = vm.$el.getElementsByTagName('h1')[0]
expect(title.textContent).toEqual('APP')
done();
})
});
});
以上就是對vue組件單元測試的用例編寫的介紹,例子舉得比較簡單派继,主要是介紹各種情況的測試方法宾袜。