在Vue項目
中測試組件時會引用全局組件,那麼如何處理這些全局組件呢? 還有Vue
中比較重要的一個點就是Vuex
如何進行測試?
1.測試時使用VueRouter
1.1 存根
在你的組件中引用了全局組件 router-link
或者 router-view
組件時,我們使用shallowMount
來渲染時會提示無法找到這兩個組件,我們可以使用存根的方式mock
掉相關的組件。
<template>
<div>
<h1>當前路由:{{this.$route.path}}</h1>
<router-link to="/">首頁</router-link>
<router-link to="/about">關於頁面</router-link>
<router-view></router-view>
</div>
</template>
import Nav from "@/components/Nav.vue";
import { shallowMount } from "@vue/test-utils";
it("測試Nav組件", () => {
let wrapper = shallowMount(Nav,{
// 忽略這兩個組件
stubs:['router-link','router-view'],
mocks:{ // mock一些數據傳入到Nav組件中
$route:{path:'/'}
}
});
expect(wrapper.find('h1').text()).toContain('/')
});
同理:我們可以mock
掉一些全局組件,也可以mock
一些參數傳入到組件中。
1.2 安裝VueRouter
我們可以也創建一個localVue
來安裝VueRouter,傳入到組件中進行渲染。
安裝 Vue Router
之後 Vue 的原型上會增加 $route
和 $router
這兩個只讀屬性。所以不要掛載到基本的Vue構造函數上,同時也不能通過mocks
參數重寫這兩個屬性
const localVue = createLocalVue();
localVue.use(VueRouter);
it("測試Nav組件", () => {
let router = new VueRouter({
routes:[
{path:'/',component:Home},
{path:'/about',component:About}
]
});
let wrapper = mount(Nav,{
localVue,
router
});
router.push('/about');
expect(wrapper.find('h1').text()).toMatch(/about/)
});
2.Vuex的測試
我們通過一個計數器
的例子來掌握如何測試vuex。
<template>
<div>
{{this.$store.state.number}}
<button @click="add(3)">添加</button>
</div>
</template>
<script>
import {mapActions} from 'vuex';
export default {
methods:{
...mapActions({'add':'increment'})
}
}
</script>
編寫store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import config from './config'
Vue.use(Vuex)
export default new Vuex.Store(config)
編寫store/mutations.js
export default {
increment(state,count){
state.number+=count
}
}
編寫store/actions.js
export default {
increment({ commit }, count) {
setTimeout(() => {
commit("increment", count);
}, 1000);
}
};
編寫store/config.js
import mutations from "./mutations";
import actions from "./actions";
export default {
state: {
number: 0
},
mutations,
actions
};
這裏我們就不過多詳細講解vuex的執行過程了,直接開始測試啦!
2.1 單元化測試store
我們可以直接把store
中的方法一一進行單元測試。
就是逐個測試函數,但是需要用mock來 commit
和dispatch
方法。
import mutations from '../mutations';
import actions from '../actions';
jest.useFakeTimers();
it('測試mutation',()=>{
const state = {number:0};
mutations.increment(state,2);
expect(state.number).toBe(2);
});
it('測試action',()=>{
let commit = jest.fn();
actions.increment({commit},2);
jest.advanceTimersByTime(2000);
expect(commit).toBeCalled();
expect(commit.mock.calls[0][1]).toBe(2);
});
2.2 測試運行的store
就是產生一個store
進行測試,好處是不需要mock
任何方法。
import Vuex from 'vuex';
import {createLocalVue} from '@vue/test-utils'
import config from '../config';
jest.useFakeTimers();
it('測試是否可以異步增加 1',()=>{
let localVue = createLocalVue();
localVue.use(Vuex);
let store = new Vuex.Store(config); // 創建一個運行store
expect(store.state.number).toBe(0);
store.dispatch('increment',2);
jest.advanceTimersByTime(2000); // 前進2s
expect(store.state.number).toBe(2);
});
config文件最好每次測試時克隆一份,保證每個用例間互不干擾!
2.3 測試組件中的Vuex
mock store
傳入組件中,看函數是否能夠如期調用。
import Vuex from 'vuex';
import Counter from '@/components/Counter';
import {createLocalVue,shallowMount} from '@vue/test-utils'
let localVue = createLocalVue();
localVue.use(Vuex);
let store;
let actions;
beforeEach(()=>{
actions = {
increment:jest.fn()
}
store = new Vuex.Store({
actions,
state:{}
});
});
it('測試組件中點擊按鈕 是否可以 1',()=>{
let wrapper = shallowMount(Counter,{
localVue,
store
});
wrapper.find('button').trigger('click');
// 測試actions中的increment 方法是否能正常調用
expect(actions.increment).toBeCalled();
})
到這裏Vuex
測試的方式我們就講解完畢了,其實前端自動化測試並沒有想象中的難,大家多多練習就可以完全掌握啦!
往期回顧:
前端自動化測試(一)
前端自動化測試(二)
前端自動化測試(三)
希望大家可以關注公衆號【前端優選】,有任何想法和意見歡迎討論交流!連續四天的連載到這裏先要告一段落了,祝大家中秋節快樂!