Vue-test-utils 模拟从另一个组件获取响应
Posted
技术标签:
【中文标题】Vue-test-utils 模拟从另一个组件获取响应【英文标题】:Vue-test-utils Mock fetch response from another component 【发布时间】:2021-03-28 22:47:54 【问题描述】:我正在尝试在一些 Vue 组件上使用 vue-test-utils
和 jest
设置单元测试,这些组件从另一个负责使用 @987654323 调用远程 API 的 Vue 组件 (ApiCalls.vue) 检索响应@。
进行 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 和 jest 配置中找不到任何线索...... 任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:首先,你不应该在 Vue 构造函数上调用 data()
函数。我的意思是,你可以只是为了踢球,但你已经知道它会返回什么,对吧?这并不神秘。 “魔术”是构造函数在返回的 Vue 实例上为data()
的每个成员创建反应属性,其值不是undefined
现在,您的模拟尝试遇到了真正的问题:您似乎误解了模拟的目的,因此也误解了单元测试的目的。模拟是用始终按照外部系统预期行为的方式替换外部系统(到您的组件)。因为您应该只测试当前单元(组件)而不是其他任何东西。您的测试不应依赖于运行测试的机器是否可以访问 API、API 当前是否已关闭等...
但是永远不要模拟被测试组件的内容!
如果您这样做,您可能会在测试仍然通过时破坏您的测试组件,因为在测试中被破坏的方法被替换为可靠的模拟。您需要一个在您的方法中运行实际代码的测试,该测试在组件失败时失败,而在组件按预期运行时通过。
您应该测试组件是否为所有可能的输入生成预期的输出。
在您的情况下,您应该模拟 ApiCalls
,使其行为符合您期望 ApiCalls
的行为,基本上您应该测试两件事:
ApiCalls.getSomeData
被调用一次(不多也不少),当当前组件被挂载时(并且使用正确的参数调用它)
当响应状态为200
时,组件的.resultsFromAPI
将填充返回的数据,否则保持null
。
您的组件不应该关心ApiCalls
是什么。换句话说,ApiCalls
应该是可模拟的。它可能是实际调用后端或后端模拟的东西。重要的是你的组件如何对ApiCalls
的方法返回的不同响应做出反应。
你可以测试的最后一件事是当ApiCalls
不可用时会发生什么,如果你认为这是一个实际的可能性(或者如果它永远不会解决会发生什么 - 它停止了)。这些是边缘情况,通常不包括在内,除非客户端有特定请求,否则应用程序应该从结构性错误中恢复(这种情况很少见)。
总而言之,永远不要编写在实际组件损坏时可以通过的测试。这是可能让你当场被解雇的事情之一(这是一个比喻——用失败时你可能失去的东西代替:客户、客户、生活、账户、声誉等),如果有任何重要的事情实际上取决于关于您的组件是否按预期执行。因为不仅您编写的测试未能捕捉到错误,而且它实际上谎称测试了组件(它从未做过 - 它测试组件模拟)。所以它给人一种虚假和危险的安全感。
使用in this answer 描述的方法来模拟ApiCalls
' 方法。
注意: 平心而论,我本可以将您的问题标记为上述问题和许多其他问题的重复。以前有人问过这个问题。 但是,我选择发布这个冗长的警告作为答案(希望您和其他人可能会发现它有用)并概述不嘲笑应该嘲笑的内容和不正确测试的危险,因为我认为这是一个大问题UT 的写作方式。 这类错误(及其危险)的部分原因还在于现在强制要求使用 UT,而很少有编码公司在教授测试原理方面付出任何努力。
【讨论】:
@Joules,即使您的组件中的方法是async
,您仍然不应该在测试中模拟该方法。您应该只模拟外部内容并检查您的组件是否发送(到模拟)它应该发送的内容,以及它是否正确处理响应。为了更好地理解原因:如果您不小心在组件的方法中键入了某些内容并且它只是中断了,您希望测试失败。如果您模拟该方法,则测试将通过,而最终用户将获得一个损坏的应用程序。以上是关于Vue-test-utils 模拟从另一个组件获取响应的主要内容,如果未能解决你的问题,请参考以下文章
使用 element-ui 和 vue-test-utils 模拟选择
vue-test-utils 的 setData 没有重新更新组件
使用 vue-test-utils / jest 触发 Quasar QBtn 点击
如何在单元测试期间使用 vue-test-utils 和 jest 模拟 mixin?