简体   繁体   English

如何在继续测试之前等待 Vue 组件的异步安装完成

[英]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.现在我想通过jestvue/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.所有测试框架( jestvitest等)都让 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.

相关问题 如何在继续async.series之前等待findOneAndUpdate完成 - How to wait for findOneAndUpdate to finish before continuing async.series 如何在单元测试之前等待异步调用在组件的挂载回调中完成? - How to wait for an async call to finish in component's mount callback before unit testing it? 如何继续等待一个功能完成? - How to wait for one function to finish before continuing? NodeJS - 如何在继续执行流程之前等待多个异步调用完成? - NodeJS - How to wait for multiple Async calls to finish before continuing execution flow? 如何在继续执行脚本之前有效地等待链接文件完成运行 - How to efficiently wait for a linked file to finish running before continuing with script 如何让程序在继续使用javascript之前等待if语句完成? - How to make the program wait for the if statement to finish before continuing in javascript? 如何在继续下一行代码之前等待 .map() 完成执行 - How to wait for .map() to finish executing before continuing on to next lines of code NodeJS Plotly - 如何在继续之前等待 getImage 完成 - NodeJS Plotly - how to wait for getImage to finish before continuing 如何在继续之前等待递归 function 完全完成? - How can I wait for a recursive function to completely finish before continuing? 如何等待 Vue function 完成异步/等待? - How to wait for a Vue function to finish with async/await?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM