为什么我的Jest MockReturnValue函数不调用? 使用Vue3和Vue-Test-Utils-Next

问题描述

我正在使用Vue的composition API并将模块导入单个文件组件中。我将模块的返回值分配给 setup 方法中的变量,然后返回该值,以便模板可以使用该变量。该组件为从导入模块接收到的每个项目呈现一个 ItemComponent

实际的应用程序可以正常工作,并且可以渲染正确数量的项目。另一方面,我的测试失败,并且似乎没有调用 mockReturnValue 函数

文件组件代码

<template>
  <ul class="ItemList">
    <ItemComponent
      v-for="item in items"
      :key="item.id"
      :item="item" />
  </ul>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import ItemComponent from '@/components/ItemComponent.vue';

import module from '@/module';

export default defineComponent({
  components: {
   ItemComponent,},setup() {
    const { items } = module.property // note destructuring here
    console.log(items);
    return { items };
  },});
</script>

mock-module.ts

export const property = {
  items: jest.fn(),};

(模拟)index.ts

import {module} from './modules/mock-module';

export default {module}

测试文件

  import module from '@/modules/__mocks__/index.ts';
  jest.mock('../../../src/modules/index.ts');

  it('should render an ItemComponent for each item',() => {
    module.property.items.mockReturnValue([{},{},{}]); // Doesn't seem to get invoked?
    const wrapper = mount(MyComponent,{ shallow: true });
    expect(wrapper.findAllComponents('item-component-stub').length)
      .toBe(3);
  });

结果

测试失败并找到0个项目,当我从单个文件组件中console.log(items)时,我得到以下信息:

 [Function: mockConstructor] {
        _isMockFunction: true,getMockImplementation: [Function (anonymous)],mock: [Getter/Setter],mockClear: [Function (anonymous)],mockReset: [Function (anonymous)],mockRestore: [Function (anonymous)],mockReturnValueOnce: [Function (anonymous)],mockResolvedValueOnce: [Function (anonymous)],mockRejectedValueOnce: [Function (anonymous)],mockReturnValue: [Function (anonymous)],mockResolvedValue: [Function (anonymous)],mockRejectedValue: [Function (anonymous)],mockImplementationOnce: [Function (anonymous)],mockImplementation: [Function (anonymous)],mockReturnThis: [Function (anonymous)],mockName: [Function (anonymous)],getMockName: [Function (anonymous)]
      }

(对我来说)这表明测试正在使用模拟文件,但是由于某种原因,它没有调用.mockReturnValue()调用。如果仅将模拟依赖项从jest.fn()更改为某个实际值,console.log语句将返回该值。当然,我不想这样做,因为我需要能够在不同的测试中设置不同的返回值。

我期望的结果 我希望当我调用module.property.items.mockReturnValue([{},{}])时,console.log将打印一个包含三个空对象的数组,并且测试将通过渲染的3/3 ItemComponents通过。

解决方法

items: jest.fn()使items成为间谍。控制台输出是应该期望的输出,它表明它是一个功能。如果测试继续,mockReturnValue将没有机会不被调用。其结果可以看作是:

module.property.items.mockReturnValue([{},{},{}])
expect(module.property.items()).toEqual([{},{}])

由于items应该是数组而不是函数,因此以错误的方式对其进行了嘲笑。通常,这是通过直接模拟属性而无需对此模块执行jest.mock来完成的:

module.property = [{},{}]

还应确保更改后的值不会影响其他测试,例如通过在jest.isolateModules中执行此操作来重新导入受影响模块的层次结构。

这也可以通过Jest间谍来完成,但是需要保留对getter函数的引用才能轻松访问它:

export const property = {
  items: null,};

export const mockPropertyItems = jest.spyOn(property,'items','get');

并用作:

module.mockPropertyItems.mockReturnValue([{},{}])
expect(module.property.items).toEqual([{},{}])

直接从__mocks__导入也是错误的,应从其常规位置导入模拟模块。