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

Vue-test-utils Mock fetch response from another component

我正在尝试在某些 Vue 组件上使用 vue-test-utilsjest 设置单元测试,这些组件从负责制作的另一个 Vue 组件 (ApiCalls.vue) 检索响应使用 fetch() 调用远程 API。 使 API 调用 returns 这种类型的对象的组件:

{
  status: <fetch response status>,
  body: <fetch response body>
}

要测试的组件概述(MyComponent.vue):

import ApiCalls from './ApiCalls.vue';

export default {
  data() {
    return {
      resultsFromAPI: null
    }
  },
  mounted() {
    this.getSomeData();
  },
  methods: {
    async getSomeData() {
      const APIResponse = await ApiCalls.data().getSomeData();
      if (APIResponse.status === 200) {
        this.resultsFromAPI = APIResponse.body;
      }
    }
  }
}

测试规范概述:

import { shallowMount } from '@vue/test-utils';
import MyComponent      from './MyComponent.vue';

const wrapper = shallowMount(MyComponent);

test('check data from API', () => {
  expect(wrapper.vm.resultsFromAPI).toBe(<stuff fromAPI>);
});

我试过像这样模拟函数 getSomeData :

wrapper.vm.getSomeData = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve({status: 200, body: { result: 'blabla' }),
  })
);

const getSomeData = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve({status: 200, body: { result: 'blabla' }),
  })
);

但它不起作用,我在 vue-test-utils 和 jest 配置中都找不到任何线索... 任何帮助将不胜感激。

首先,你不应该在 Vue 构造函数上调用 data() 函数。我的意思是,你可以只是为了好玩而做,但你已经知道它会发生什么 return,对吧?这并不神秘。 “魔法”是构造函数在 returned Vue 实例上为 data() 结果的每个成员创建反应属性,其值不是 undefined

现在,通过模拟尝试解决真正的问题:您似乎误解了模拟的目的,因此也误解了单元测试的目的。 Mocking 正在将外部系统(对您的组件)替换为始终表现出外部系统预期行为的东西。因为您应该只测试当前单元(组件)而不是其他任何东西。你的测试不应该依赖于测试机器 运行 是否可以访问 API,如果 API 当前关闭,等等...

但是永远不要模拟正在测试的组件的内容!

如果你这样做,你的测试组件就有可能在测试仍然通过时被破坏,因为破坏的方法在测试中被替换为可靠的模拟。您想要一个在您的方法中运行实际代码的测试,当组件失败时测试失败,当组件按预期运行时测试通过。

您应该测试组件是否为所有可能的输入生成预期的输出。

在你的情况下,你应该模拟 ApiCalls 的行为与你期望 ApiCalls 的行为一样,基本上你应该测试两件事:

  • ApiCalls.getSomeData 被调用一次(不少于,不多),当前组件已安装(并且使用正确的参数调用)
  • 组件的 .resultsFromAPI 在响应状态为 200 时填充 returned 数据,否则保持 null

您的组件不应该关心 ApiCalls 是什么。换句话说,ApiCalls 应该是可模拟的。它可能是实际调用后端或后端模拟的东西。重要的是您的组件如何对来自 ApiCalls 方法 return.

的不同响应做出反应

你可以测试的最后一件事是当 ApiCalls 不可用时会发生什么,如果你认为这是一个实际的可能性(或者如果它永远不会解决会发生什么 - 它会停止)。这些是边缘情况,通常不包括在内,除非有来自客户端的特定请求,应用程序应该从结构错误中恢复(这种情况很少见)。


总而言之,永远不要编写在实际组件损坏时可以通过的测试。这是可能让你当场被解雇的事情之一(这是一个比喻——用失败时你可能失去的任何东西来代替:客户、客户、生命、账户、声誉等……),如果任何重要的事情实际上取决于关于您的组件是否按预期执行。因为不仅您编写的测试未能捕获错误,而且它实际上谎称已经测试了组件(它从来没有这样做 - 它测试了组件模拟)。所以给人一种虚假和危险的安全感。


使用 描述的方法模拟 ApiCalls 方法。

注意: 平心而论,我本可以将您的问题标记为与上述问题和许多其他问题重复。之前有人问过这个问题。
然而,我选择 post 这个冗长的警告作为答案(希望你和其他人会发现它有用)并概述了不嘲笑应该嘲笑的东西和不正确测试的危险,正如我认为的那样UT 的书写方式经常是个大问题。
造成此类错误(及其危险)的部分原因还在于如今 UT 已成为强制性要求,而很少有编码公司投入任何精力来教授测试原则。