Vue-test-utils 模拟来自另一个组件的获取响应



我正在尝试使用vue-test-utilsjest对某些 Vue 组件进行单元测试,这些组件从另一个 Vue 组件 (ApiCalls.vue) 检索响应,该组件负责使用fetch()调用远程 API。 进行 API 调用的组件返回以下类型的对象:

{
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 或开玩笑的配置中找不到任何线索...... 任何帮助将不胜感激。

首先,你永远不应该在 Vue 构造函数上调用data()函数。我的意思是,你可以只为踢球而做,但你已经知道它会返回什么,对吧?这并不神秘。"魔术"是构造函数在返回的 Vue 实例上为data()结果的每个成员创建反应式属性,其值不是undefined

现在,进入你的嘲笑尝试的真正问题:你似乎误解了嘲笑的目的,因此误解了单元测试的目的。模拟是将外部系统(到您的组件)替换为始终与外部系统预期行为相同的内容。因为您应该只测试当前单元(组件),而不应测试其他任何单元。您的测试不应取决于运行测试的计算机是否有权访问 API、API 当前是否关闭等......

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

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

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

在你的情况下,你应该用一些你期望的行为来模拟ApiCallsApiCalls的行为基本上你应该测试两件事:

  • ApiCalls.getSomeData在当前组件被挂载时调用一次(不少于,不超过),并且使用正确的参数调用它)
  • 当响应状态为200时,组件的.resultsFromAPI将使用返回的数据填充,否则将保持null

您的组件不应该关心ApiCalls是什么。换句话说,ApiCalls应该是可模拟的。它可以是实际调用后端或后端模拟的东西。重要的是你的组件如何对来自任何ApiCalls方法返回的不同响应做出反应。

您可以测试的最后一件事是,如果您认为ApiCalls不可用时会发生什么(或者如果它永远不会解决会发生什么 - 它会停滞不前)。这些是边缘情况,通常不会涵盖,除非客户端有特定请求,否则应用程序应从结构错误中恢复(这种情况很少见)。


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


使用本答案中描述的方法模拟ApiCalls'方法。

注意:平心而论,我本可以将您的问题标记为上述问题和许多其他问题的重复。
但是,我选择发布这个冗长的警告作为答案(希望你和其他人会发现它有用),并概述不嘲笑应该嘲笑的内容和没有正确测试的危险,因为我认为UT通常如何编写是一个大问题.
这种类型的错误(及其危险)的一些责任也在于如今,UT成为强制性的,而很少有编码公司致力于教授测试原则。

最新更新