使用 `vue-test-utils` 和 `jest` 使用 `Created` 钩子进行测试

Posted

技术标签:

【中文标题】使用 `vue-test-utils` 和 `jest` 使用 `Created` 钩子进行测试【英文标题】:Testing with `Created` hook with `vue-test-utils` and `jest` 【发布时间】:2019-09-26 22:05:39 【问题描述】:

我有一个这样的 Vue 页面:

<template>
</template>

<script>
created()
    this.doSomething();


methods: 
    doSomething() 
        .....
    


</script>

现在,我们要测试这个创建的钩子并检查是否调用了 doSomething() 方法。

这样试了,在package.json中也导入jest

import 
  shallowMount,
  createLocalVue,
 from '@vue/test-utils';

const localVue = createLocalVue();

import Xyx from '/Xyx.vue';

const init = () => 
  wrapper = shallowMount(Xyx,  localVue );
  cmp = wrapper.vm;
;

describe('#created', () => 
  it('#doSomething', () => 
    init();
    wrapper.setMethods(
      doSomething: jest.fn(),
    )
    expect(cmp.doSomething).toHaveBeenCalled();
  );
);

我可以做这个创建的钩子的单元测试用例吗?

【问题讨论】:

【参考方案1】:

因为您的方法是在 created 上调用的,所以它在您设置模拟之前运行。因此,您的测试将失败。 您必须在初始化时用模拟替换该方法(在您的情况下,在 shallowMount 上):

describe('Xyz', () => 
  it('should call doSomething() when created', () => 
    const doSomething = jest.fn()
    wrapper = shallowMount(Xyz, 
      localvue,
      methods:  doSomething 
    );
    expect(doSomething).toHaveBeenCalled();
  );
);

旁注:您没有声明cmp。在测试开始时,您应该有一个let cmp;


一个非常相似的讨论here。在链接的评论上方,有一个方法可以模拟大多数 Vue 组件生命周期钩子的属性。

【讨论】:

应该是expect(doSomething).toHaveBeenCalled();否则会报错Matcher error: received value must be a mock or spy function @tao,谢谢你的方法。但是,expect(wrapper.vm.doSomething) 对我不起作用,并返回了@WhosDustin 指定的错误。 @WhosDustin,感谢您的更正,我的测试运行成功。 @elushnikova,请提出一个新问题并提供相关代码。如果您已经完成了上述操作(模拟了该方法,将其放置在 shallowMount 或 mount 的方法中,并完成了该组件应该执行的任何操作以触发该方法)它应该可以工作。没有看到你的代码,我无能为力。错误 per-se 表明您无法评估该方法是否被调用,因为它没有被模拟(它没有被间谍函数替换,如我的示例所示)。 我也确认了@WhosDustin 提到的错误,他的解决方案有效【参考方案2】:

methods 选项在 @vue/test-utils 的 v1 中已弃用,因此接受的答案不再有效。我自己遇到了这个问题,并决定深入研究源代码以找出如何测试它。

看起来 Vue 实际上将所有挂钩存储在 $options 属性中。每个钩子都有一个选项,它是一组函数。需要注意的是,上下文并不绑定到所述函数,因此您需要使用callapply 来执行它们。

vm.$options.created.forEach(hook => 
  hook.call(vm);
);

【讨论】:

你能举个完整的例子吗?【参考方案3】:

当我们需要在我们的测试中调用钩子是可能的。例如,如果我们需要在调用钩子之前模拟一些数据。

import App from '@/App.vue';

// in test
App.created.call(wrapper.vm);

同样在 Typescript 中,如果我们使用 vue-property-decorator 它会改变组件的形状,所以需要这样做:

App.extendOptions.created.call(wrapper.vm)

【讨论】:

以上是关于使用 `vue-test-utils` 和 `jest` 使用 `Created` 钩子进行测试的主要内容,如果未能解决你的问题,请参考以下文章

使用 element-ui 和 vue-test-utils 模拟选择

如何在单元测试期间使用 vue-test-utils 和 jest 模拟 mixin?

vue-test-utils:在同一个测试中模拟 vue-router 和 vuex

(vue-test-utils) '不能覆盖属性 $route,...'

Vue-test-utils 模拟从另一个组件获取响应

Vue-test-utils 在 nuxt 中使用 mixin 进行 vee-validate