使用注入加载器模拟Vue类组件方法

时间:2017-11-21 11:02:30

标签: javascript vue.js vuejs2 vue-component

假设我有一个非常基本的 vue-class-component ,如下所示:

<template>
    <div>Nothing of interest here</div>
</template>

<script>
    import Vue from 'vue';
    import Component from 'vue-class-component';
    import http from './../modules/http';

    @Component
    export default class Example extends Vue {
        user = null;
        errors = null;

        /**
         * @returns {string}
         */
        getUserId() {
            return this.$route.params.userId;
        }

        fetchUser() {
            this.user = null;
            this.errors = null;

            http.get('/v1/auth/user/' + this.getUserId())
                .then(response => this.user = response.data)
                .catch(e => this.errors = e);
        }
    }
</script>

我想测试fetchUser()方法,因此我只是嘲笑'./../modules/http'依赖项并让http.get返回Promise。问题是,在我的断言中,我想检查URL是否正确构建,为了做到这一点,用户ID必须来自测试中的硬编码变量。

我尝试了类似的东西,但它不起作用:

import ExampleInjector from '!!vue-loader?inject!./../../../src/components/Example.vue';

const mockedComponent = ExampleInjector({
    './../modules/http': {
        get: () => new Promise(/* some logic */)
    },
    methods: getUserId: () => 'my_mocked_user_id'
});

不幸的是它不起作用,我在Vue文档中找不到任何特定内容,所以问题是,我应该如何模拟外部依赖项和类组件方法?

注意:我不想模仿this.$route.params.userId因为userId也可能来自其他地方(加上这只是一个例子)。我只是想模仿getUserId方法。

2 个答案:

答案 0 :(得分:2)

最简单的方法是扩展组件并覆盖方法:

const Foo = Vue.extend({
  template: `<div>{{iAm}}</div>`,
  created() {
    this.whoAmI();
  },
  methods: {
    whoAmI() {
      this.iAm = 'I am foo';
    }
  },
  data() {
    return {
      iAm: ''
    }
  }
})

Vue.component('bar', {
  extends: Foo,
  methods: {
    whoAmI() {
      this.iAm = 'I am bar';
    }
  }
})

new Vue({
  el: '#app'
})

在此示例中,我使用extends属性告诉Vue Bar扩展Foo,然后我覆盖了whoAmI方法,你可以在这里看到这是行动:https://jsfiddle.net/pxr34tuz/

我在我的一个开源项目中使用类似的东西,你可以查看here。我在该示例中所做的就是关闭道具所需的属性以阻止Vue向我抛出控制台错误。

答案 1 :(得分:2)

由于我特意询问我如何使用注入加载器模拟Vue类组件方法,这里是问题的完整解决方案:

import ExampleInjector from '!!vue-loader?inject!./../../../src/components/Example.vue';

const getComponentWithMockedUserId = (mockedUserId, mockedComponent = null, methods = {}) => {
    if (!mockedComponent) {
        mockedComponent = ExampleInjector();
    }

    return Vue.component('test', {
        extends: mockedComponent,
        methods: {
            getUserId: () => mockedUserId,
            ...methods
        }
    });
};

然后在我的测试用例中:

const component = getComponentWithMockedUserId('my_mocked_user_id');

const vm = new Vue(component);

我发现当你需要创建一个部分模拟 AND 注入一些依赖项时,这非常有用。