Vue-test-utils 模拟从另一个组件获取响应
Vue-test-utils Mock fetch response from another component
我正在尝试在某些 Vue 组件上使用 vue-test-utils
和 jest
设置单元测试,这些组件从负责制作的另一个 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 已成为强制性要求,而很少有编码公司投入任何精力来教授测试原则。
我正在尝试在某些 Vue 组件上使用 vue-test-utils
和 jest
设置单元测试,这些组件从负责制作的另一个 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 已成为强制性要求,而很少有编码公司投入任何精力来教授测试原则。