前端自動化測試(四)

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來 commitdispatch方法。

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測試的方式我們就講解完畢了,其實前端自動化測試並沒有想象中的難,大家多多練習就可以完全掌握啦!

往期回顧:
前端自動化測試(一)
前端自動化測試(二)
前端自動化測試(三)

希望大家可以關注公衆號【前端優選】,有任何想法和意見歡迎討論交流!連續四天的連載到這裏先要告一段落了,祝大家中秋節快樂!

圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章