这篇文章主要介绍了jest单元测试mock数据的一些常见情况。

##

  • axios.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    const mockAxios = jest.genMockFromModule('axios');
    import {
    BASE_URL
    } from '@/views/Content/Financial/api/utils.js'
    // this is the key to fix the axios.create() undefined error!

    mockAxios.create = jest.fn(() => mockAxios);
    mockAxios.get = jest.fn((url) => {
    if (url === '') {
    return Promise.resolve({
    data: {
    code: '200'
    }
    })
    }
    return Promise.resolve({
    data: {
    code: '200'
    }
    })
    });
    mockAxios.post = jest.fn((url) => {
    if (url === `${BASE_URL}/paymentmethodtype/pageQuery`) {
    return Promise.resolve({
    data: {
    code: '200',
    data: {
    totalRecord: 10,
    list: [{
    id: 1,
    paymentmethodtypeguid: 1,
    paymethods: 1,
    paytype: 1,
    selectcontent: 1
    }]
    }
    }
    })
    }
    if (url === `${BASE_URL}/myparamvalue/pageQuery`) {
    return Promise.resolve({
    data: {
    code: '200',
    data: {
    totalRecord: 10,
    list: [{
    id: 1,
    paymentmethodtypeguid: 1,
    paymethods: 1,
    paytype: 1,
    selectcontent: 1
    }]
    }
    }
    })
    }
    if (url === `${BASE_URL}/paymentmethodtype`) {
    return Promise.resolve({
    data: {
    code: '200'
    }
    })
    }
    return Promise.resolve({
    data: {
    code: '200'
    }
    })
    });

    mockAxios.put = jest.fn(() => Promise.resolve({
    data: {}
    }));
    mockAxios.patch = jest.fn(() => Promise.resolve({
    data: {}
    }));
    mockAxios.delete = jest.fn(() => {
    // if (url === `${BASE_URL}/paymentmethodtype/delete`) {
    // return Promise.resolve({ data: { code: '200' } })
    // }
    return Promise.resolve({
    data: {
    code: '200'
    }
    })
    });
    mockAxios.all = jest.fn(() => Promise.resolve());

    export default mockAxios;
  • fileMock.js

    1
    module.exports = 'test-file-stub';
  • localStorageMock.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    global.window = Object.create(window);
    var storage = {};
    Object.defineProperty(window, 'localStorage', {
    value:{
    setItem: function(key, value) {
    storage[key] = value || '';
    },
    getItem: function(key) {
    return key in storage ? storage[key] : null;
    },
    removeItem: function(key) {
    return delete storage[key]
    },
    }
    })
  • mockRoute.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // mock出来的router,为了部分测试方便,mock数据
    const mocksRouter = {
    //demo
    login: {
    name: 'login',
    path: 'login',
    meta: {
    title: '登录'
    },
    hash: '',
    query: { token: '123' }
    },
    }

    // 复制真实的router,避免污染全局,无特殊需要用此路由即可
    const copyRouter = {}
    module.exports = {
    copyRouter,
    mocksRouter
    }
  • mockStore.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    const copyStore = {
    state: {},
    mutations: {},
    actions: {},
    getters:{}
    }

    const mockStore = {
    $store: {
    state: {},
    commit() {},
    getters: {
    userAccess: jest.fn(),
    },
    dispatch: jest.fn()
    }
    }

    module.exports = {
    copyStore,
    mockStore
    }
  • mockWindowMethod.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    //模拟全局变量 demo
    Object.defineProperty(window, 'zhuge', {
    value: {
    track: function (key, value) {},
    }
    });

    Object.defineProperty(window, 'navigator', {
    value: {
    userAgent: 'iPhone'
    }
    });

    Object.defineProperty(window, 'open', {
    value: () => {}
    });
  • styleMock.js

    1
    module.exports = {}
  • vueBase.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    import { shallowMount, createLocalVue,} from '@vue/test-utils'
    import { mocksRouter, copyRouter} from './mockRoute'
    import { mockStore, copyStore} from './mockStore'
    import Vuex from 'vuex'
    import VueRouter from 'vue-router'

    const data = {
    data: {
    code: '200',
    data: {},
    message: 'OK'
    }
    }

    const getVue = (obj) => {
    const localVue = createLocalVue()
    localVue.use(Vuex)
    let store
    let mockRoute
    beforeEach(() => {
    store = new Vuex.Store(copyStore)
    })

    if (obj.callback) {
    obj.callback(localVue)
    }

    if (typeof obj.routerName == undefined) {
    localVue.use(VueRouter)
    mockRoute = {}
    } else {
    mockRoute = {
    $route: mocksRouter[obj.routerName] || {},
    $router: {
    push: jest.fn()
    },
    }
    }

    return shallowMount(obj.component, {
    localVue,
    stubs: ['router-link', 'router-view'],
    mocks: {
    ...mockStore,
    ...mockRoute,
    $alert() {},
    ...(obj.mocks || {}),
    },
    directives: {
    blur: jest.fn()
    },
    ...(obj.cover || {}),
    })
    }

    module.exports = {
    getVue,
    data
    }

.eslintrc.js

1
2
3
4
5
module.exports = {
env: {
jest: true
}
}

specs

  • App.spec.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import {shallowMount, createLocalVue} from '@vue/test-utils'
    import App from '@/App.vue'
    // import sinon from 'sinon'
    import VueRouter from 'vue-router'
    const localVue = createLocalVue()
    localVue.use(VueRouter)
    const router = new VueRouter()
    describe('App.vue', () => {
    const wrapper = shallowMount(App, {
    localVue,
    router
    })
    it('simple test', () => {
    expect(App.name).toBe('App')
    })
    })
  • lang.spec.js

    1
    2
    3
    4
    5
    6
    7
    8
    // 导入 Vue.js 和组件,进行测试
    import lang from '@/lang/index'
    describe('lang', () => {
    it('messages', () => {
    expect(lang.hasOwnProperty('_vm')).toBe(true)
    expect(lang.messages.hasOwnProperty('zh')).toBe(true)
    })
    })
  • views/page

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    import vue from 'vue'
    import axios from 'axios'
    import elementUi from 'element-ui'
    import RuleTables from '@/views/Content/ProjectPreparation/components/RuleTable'
    import { getVue, data } from '../../../../../__mocks__/vueBase'
    import DictSelect from '@/components/DictSelect/index.vue'
    vue.component(DictSelect.name, DictSelect)

    import '@/directives/index' // 如果使用了指令要引入

    jest.mock('axios')

    describe('RuleTables.vue', () => {
    const wrapper = getVue({
    component: RuleTables,
    mocks: {
    window: { // window 对象
    open: ()=>{}
    },
    $refs: { // refs
    formRef: {
    validate: jest.fn(() => {}),
    resetFields: jest.fn(() => {}),
    }
    },
    $store: { // store
    state: {
    paramSetting: {
    treeData: {}
    }
    },
    getters: {},
    commit: jest.fn(() => {}),
    },
    $route: { // 路由
    params: {
    id: '1'
    }
    }
    },
    cover: {
    computed: { // 模拟computed
    DICT_CALC_TYPE: {
    get: jest.fn(() => 'DICT_CALC_TYPE'),
    set: jest.fn()
    },
    },
    data() { // data
    return {
    treeNode:{}
    }
    }
    },
    callback(Vue) {
    Vue.use(elementUi);
    }
    })

    const vm = wrapper.vm;
    it('RuleTables test 是否存在', () => {
    expect(RuleTables.name).toBe('RuleTables')
    })


    it('snapshot测试DOM结构', () => {
    expect(wrapper.html()).toMatchSnapshot()
    })
    })