Vuejs单元测试 - 通过测试支持模拟

时间:2017-04-28 14:41:23

标签: laravel unit-testing jasmine vue.js vuex

我正在为使用Vuex作为商店的vuejs 2应用程序编写单元测试。我的许多组件都有以下模式:

示例组件thing.vue:

<template>
    <div>
        {{ thing.label }}
    </div>
</template>
<script>
  export default {
    name: 'thing',
    data() { return { } },
    computed: {
       thing () {
         return this.$store.state.thing;
       }
    }
  }

</script>

示例商店状态:

export const state = {
    thing: { label: 'test' }
};

Thing.vue的示例单位:

describe('thing ', () => {

  const storeMock = new Vuex.Store( state: { thing: { label: 'test' } } );

  it('should pull thing from store', () => {
      const Constructor = Vue.extend(thing);
      const component new Constructor({ store }).$mount();

      expect(component.thing).toEqual({ label: 'test' });
  });

});

商店的单元测试示例:

import store from './store';

describe('Vuex store ', () => {

  it('should have a thing object', () => {
      expect(store.state.thing).toEqual({ label: 'test' });
  });

});

这种模式存在很大问题。当另一个开发人员折射存储状态时,他们会看到存储测试失败,但是因为事物单元测试基于测试的模拟版本继续传递,即使该组件永远不会工作。知道重构无效的模拟方法并不是一个好方法。

那么人们如何对这种依赖进行单元测试?

一种方法是在单元测试中作弊并使用实际存储状态,但它不是真正的单元测试。另一种方法是依靠集成测试来捕捉模拟 - 存储不匹配,但感觉调试为什么单元测试通过但集成测试失败会很痛苦。

1 个答案:

答案 0 :(得分:0)

我们最终做的是使用实际商店。因为商店状态只是一个对象,我们认为它是可以接受的。

我们还使用商店的吸气剂,动作和突变作为茉莉花谍的模板。

// Vuex needs polyfill
import { polyfill } from 'es6-promise';
polyfill();
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

import test from 'app/components/test.vue';
import module from 'app/store/modules/module';


describe('Spec for Test.vue', () => {
    var props;
    var state;
    var actions;
    var mutations;
    var getters;
    var store;

    beforeEach( () => {
        jasmine.addMatchers(customMatchers);
        props = { };

        // Don't change the modules
        state = Object.assign({}, module.state);
        actions = Object.assign({}, module.actions);
        mutations = Object.assign({}, module.mutations);
        getters = Object.assign({}, module.getters);

        // Add require global actions, mutations, and getters here...
        actions.globalActionHere = 'anything'; // this turns into a spy

        // Update State with required fields
        state.defaults = { id: 1 }   // default expected when the component loads

        // Replace modules copies with mocks
        actions = jasmine.createSpyObj('actions', actions);
        mutations = jasmine.createSpyObj('mutations', mutations);
        getters = jasmine.createSpyObj('getters', getters);

        store = new Vuex.Store( { state: { module: state }, getters, actions, mutations } );
    } );

    it('should have a name of test', () => {
        const Constructor = Vue.extend(thing);
        const component new Constructor({ store, props }).$mount();

        expect(component.$options.name).toBe('test');
    });

});

注意部分

jasmine.createSpyObj('actions', actions);

Jasmine spies将使用该模块为每个方法创建spyies,这非常有用。