Estoy tratando de obtener los resultados de un backend simulado en Angular 2 para pruebas unitarias. Actualmente, estamos usando fakeAsync con un tiempo de espera para simular el paso del tiempo.
prueba de unidad de trabajo actual
it('timeout (fakeAsync/tick)', fakeAsync(() => { counter.getTimeout(); tick(3000); //manually specify the waiting time })); Pero, esto significa que estamos limitados a un tiempo de espera definido manualmente. No cuando se completa la tarea asíncrona. Lo que estoy tratando de hacer es hacer que tick() espere hasta que se complete la tarea antes de continuar con la prueba.
Esto no parece funcionar según lo previsto.
Leer sobre fakeAsync y tick la respuesta aquí explica que:
tick() simula el paso asincrónico del tiempo.
Configuré un ejemplo de plnkr que simulaba este escenario.
Aquí, llamamos al método getTimeout() que llama a una tarea asíncrona interna que tiene un tiempo de espera. En la prueba, intentamos envolverlo y llamar a tick() después de llamar al método getTimeout() .
contador.ts
getTimeout() { setTimeout(() => { console.log('timeout') },3000) }contador.specs.ts
it('timeout (fakeAsync/tick)', fakeAsync(() => { counter.getTimeout(); tick(); }));Pero la prueba unitaria falla con el error "Error: 1 temporizador(es) todavía en la cola".
¿El problema aquí en el repositorio angular tiene algo que ver con esto?
¿Es posible usar tick() de esta manera para esperar una función de tiempo de espera? ¿O hay otro enfoque que pueda usar?
El propósito de fakeAsync es controlar el tiempo dentro de su especificación. tick no esperará ningún tiempo ya que es una función síncrona utilizada para simular el paso del tiempo. Si desea esperar hasta que se complete la función asíncrona, necesitará usar async y whenStable , sin embargo, en su ejemplo, la especificación tardará 3 segundos en pasar, por lo que no recomendaría esto.
La razón por la que counter.spec.ts está fallando es que solo ha simulado el paso de 0 segundos (generalmente se usa para representar el siguiente tic del ciclo de eventos). Entonces, cuando la especificación se completa, todavía hay temporizadores simulados activos y eso falla en toda la especificación. En realidad, funciona correctamente al informarle que se ha burlado de un tiempo de espera y no se ha manejado.
Básicamente, creo que está intentando usar fakeAsync y tick en formas para las que no estaban destinados a usarse. Si necesita probar un tiempo de espera de la manera que ha propuesto, la forma más sencilla sería simular la función setTimeout usted mismo para que, independientemente del tiempo utilizado, pueda simplemente llamar al método.
EDITADO Me encontré con un problema relacionado en el que quería borrar los temporizadores y, dado que no era la parte que se estaba probando, no me importaba cuánto tiempo tomó. Lo intenté:
tick(Infinity);Lo cual funcionó, pero fue súper hacky. terminé yendo con
discardPeriodicTasks();Y todos mis temporizadores fueron borrados.
Intente agregar una o una combinación de las siguientes llamadas de función al final de su prueba:
flush(); flushMicrotasks(); discardPeriodicTasks();flush (con el parámetro maxTurns opcional) también vacía las macrotareas. (Esta función no se menciona en el tutorial de prueba de Angular).flushMicrotasks la cola de microtareas.discardPeriodicTasks cancela "temporizador(es) peridódico(s) aún en la cola".Los temporizadores en la cola no significan necesariamente que haya un problema con su código. Por ejemplo, los componentes que observan la hora actual pueden introducir dichos temporizadores. Si usa dichos componentes de una biblioteca extranjera, también podría considerar agregarlos en lugar de "perseguir temporizadores".
Para una mayor comprensión, puede consultar el código javascript de la función fakeAsync en zone-testing.js .
Al final de cada prueba agregue:
fixture.destroy(); flush();