Tengo un componente Vue2 con un método de enlace de ciclo de vida asíncrono:
// create report when component is loading async mounted(): Promise<void> { await this.createReport(); } Ahora me gustaría probar mi componente a través de jest y vue/test-utils pero la prueba debe await a que se complete el método de mounted() del componente.
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 Desafortunadamente mount() o shallowMount() no devuelven una Promise y no esperarán a que se complete el enlace del ciclo de vida.
Hasta ahora, la única opción era await flushPromises() , que no tiene efecto en el método montado. Otros escribieron await mount() pero como no se devuelve ninguna Promesa, esto tampoco tiene efecto. Creo que la mayoría de las pruebas pasan, porque son lo suficientemente rápidas como para que el montaje ya esté terminado. Lo cual no es mi caso, ya que estamos cargando algunos datos adecuados y eso lleva unos segundos.
Un usuario verá una pantalla de carga y esperará pacientemente para interactuar con el componente, pero lamentablemente no esperará.
¿Cómo puedo comenzar mis pruebas de Vue con broma después de que la lógica montada haya terminado?
Si marca mounted como async , no impide que el componente se monte hasta que la promesa se resuelva/rechace 1 . Se mounted y, en algún momento posterior, se resolverá/rechazará.
Si desea esperar hasta que suceda algo (p. ej., se resuelve this.createReport() ), dentro de su mounted , después de await , establezca un valor booleano en true (p. ej., this.hasReport ).
Ahora puede watch ese valor de datos reactivos y activar alguna otra funcionalidad o puede usarlo dentro de su <template> para evitar que se represente algún DOM antes de que tenga los datos necesarios.
La forma típica de probar el comportamiento asíncrono es simular la respuesta asíncrona. No nos ha mostrado lo que createReport() pero es probable que sea externo a la lógica del componente. Para las pruebas unitarias, realmente no importa lo que haga. Debe simular todos los casos que desea probar (resolver éxito, rechazar falla, ...).
¿Por qué burlarse? Porque, por ejemplo, no desea que sus pruebas fallen si Internet no funciona cuando ejecuta las pruebas. Por lo tanto, no debería realizar una solicitud http real a una API distante. Debe reemplazar esa llamada con una función (simulacro), devolviendo una promesa que se resuelve con los datos esperados. O rechazar con el error esperado.
Todos los marcos de prueba ( jest , vitest , etc...) hacen que burlarse sea muy fácil.
Consulte prueba de comportamiento asíncrono .
1 - Técnicamente, esta afirmación solo es 100 % cierta en Vue 2. Vue 3 tiene un componente <Suspense> experimental integrado, que tiene dos ranuras: el contenido y el respaldo. Si algún componente, sin importar qué tan profundo, dentro de la ranura de contenido tiene ganchos created y/o mounted asíncronamente, el componente <Suspense> representará el contenido de la ranura de reserva, hasta que todas las promesas de contenido se resuelvan o rechacen. Cuando todos lo hayan hecho, se mostrará el espacio de contenido.
Esto no es relevante para su caso, ya que está utilizando Vue 2, pero tuve que especificarlo para evitar confusiones para los usuarios de Vue 3.