【问题标题】:Vuejs Unit Test - Backing Mocks with TestsVuejs 单元测试 - 用测试支持模拟
【发布时间】:2017-09-26 17:31:41
【问题描述】:

我正在为一个使用 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' });
  });

});

Store 的示例单元测试:

import store from './store';

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

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

});

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

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

一种方法是在单元测试中作弊并使用真实的存储状态,但这并不是真正的单元测试。另一种方法是依靠集成测试来捕捉模拟存储不匹配的情况,但这感觉就像调试单元测试通过但集成测试失败的原因会很痛苦。

【问题讨论】:

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


    【解决方案1】:

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

    我们还使用 store getter、actions 和 mutation 作为 jasmine spyies 的模板。

    // 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,这非常有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-13
      • 2013-02-22
      • 2011-04-11
      • 2020-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多