[英]How to wait for async mounted of Vue component to finish before continuing with testing
I have a Vue2
component with a async lifecycle hook method:我有一个带有异步生命周期钩子方法的
Vue2
组件:
// create report when component is loading
async mounted(): Promise<void> {
await this.createReport();
}
Now I would like to test my component via jest
and vue/test-utils
but the test should await
the completion of the component's mounted()
method.现在我想通过
jest
和vue/test-utils
测试我的组件,但测试应该await
组件的mounted()
方法完成。
const wrapper = await mount(MyComponent, { // <-- no Promise, await has no effect
localVue
});
await flushPromises(); // <-- is not waiting for the async mounted()
expect(wrapper.vm.currentReport.sections).toHaveLength(5); // <-- failing since createReport not finished
Unfortunately mount()
or shallowMount()
do not return a Promise
and will not wait for the completion of the lifecycle hook.不幸的是
mount()
或shallowMount()
不会返回一个Promise
并且不会等待生命周期钩子的完成。
So far the only option was await flushPromises()
which has no effect on the mounted method.到目前为止,唯一的选择是
await flushPromises()
,它对挂载的方法没有影响。 Others wrote await mount()
but since no Promise is returned, this has also no effect.其他人写了
await mount()
但由于没有返回 Promise,这也没有效果。 I think most tests pass, because they are just fast enough so the mounted is finished already.我认为大多数测试都通过了,因为它们足够快,所以安装已经完成。 Which is not the case for me, since we are loading some proper data and that takes a few seconds.
这对我来说不是这样,因为我们正在加载一些正确的数据,这需要几秒钟。
A user will see a loading screen and will wait patiently to interact with the component, jest unfortunately will not wait.用户将看到加载屏幕并耐心等待与组件交互,不幸的是不会等待。
How can I start my Vue tests with jest after the mounted-logic has finished?在挂载逻辑完成后,如何用 jest 开始我的 Vue 测试?
If you mark mounted
as async
you are not preventing the component from mounting until the promise resolved/rejected 1 .如果您将
mounted
标记为async
,则在promise resolve/rejected 1之前,您不会阻止组件安装。 It will mount and, at some later point, mounted
will resolve/reject.它将挂载,并在稍后的某个时间点,
mounted
将解析/拒绝。
If you want to wait until something happens (eg: this.createReport()
resolves), inside your mounted
, after the await
, set a boolean to true
(eg: this.hasReport
).如果您想等到某事发生(例如:
this.createReport()
解决),在您的mounted
内,在await
之后,将布尔值设置为true
(例如: this.hasReport
)。
Now you can watch
that reactive data value and trigger some other functionality or you can use it inside your <template>
to prevent some DOM from rendering before it has the necessary data.现在,您可以
watch
该反应数据值并触发其他一些功能,或者您可以在<template>
中使用它来防止某些 DOM 在它拥有必要的数据之前呈现。
The typical way to test async behaviour, is to actually mock the async response.测试异步行为的典型方法是实际模拟异步响应。 You haven't shown us what
createReport()
does but it's likely external to the component logic.您尚未向我们展示
createReport()
的作用,但它可能在组件逻辑之外。 For unit tests, it doesn't really matter what it does.对于单元测试,它做什么并不重要。 You should mock all the cases you want to test (resolve success, reject failure, ...).
您应该模拟所有要测试的案例(解决成功,拒绝失败,...)。
Why mock?为什么要嘲讽? Because, for example, you don't want your tests to fail if the internet is not working when you run the tests.
因为,例如,如果在运行测试时 Internet 不工作,您不希望测试失败。 So you shouldn't be making an actual http request to some distant API.
因此,您不应该向某个遥远的 API 发出实际的 http 请求。 You should replace that call with a function (mock), returning a promise resolving with the expected data.
您应该用一个函数(模拟)替换该调用,返回一个用预期数据解析的承诺。 Or rejecting with the expected error.
或以预期的错误拒绝。
All testing frameworks ( jest
, vitest
, etc...) make mocking a breeze.所有测试框架(
jest
、 vitest
等)都让 mocking 变得轻而易举。
See testing async behavior .请参阅测试异步行为。
1 - Technically, this statement is only 100% true in Vue 2. Vue 3 has a built-in experimental <Suspense> component, which has two slots: the content and the fallback. 1 - 从技术上讲,这个陈述在 Vue 2 中只有 100% 正确。Vue 3 有一个内置的实验性<Suspense>组件,它有两个插槽:内容和后备。 If any component, no matter how deep, inside the content slot has asynchronous
created
and/or mounted
hooks, the <Suspense>
component will render the fallback slot contents, until all the content promises resolve or reject.如果内容槽内的任何组件,无论多深,都具有异步
created
和/或mounted
的钩子, <Suspense>
组件将呈现回退槽内容,直到所有内容承诺解决或拒绝。 When all of them have, it will display the content slot.当它们都具有时,它将显示内容槽。
This is not relevant for your case, since you're using Vue 2, but I had to specify it to avoid confusion for Vue 3 users.这与您的情况无关,因为您使用的是 Vue 2,但我必须指定它以避免对 Vue 3 用户造成混淆。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.