FakeAsync garantisce il completamento promesso dopo tick / flushMicroservice

Il problema principale è come verificare che le azioni previste siano state eseguite una volta completata una Promessa, ad esempio per verificare se un componente aggiorna correttamente i suoi stati dopo aver ricevuto alcuni contenuti remoti.

Nelle specifiche seguenti, dealWithIt() simula una logica eseguita in risposta a una promise completata (aggiorna la variabile e triggers “un altro evento asincrono”).

 it('Promises fulfilled by flushMicrotasks',fakeAsync((): void => { let x = 1; let y = 2; let dealWithIt = function(p:Promise) { p.then( v => { x = v; Promise.resolve(v).then( v=> {y = v+1; }); }); }; let p = Promise.resolve(y); dealWithIt(p); flushMicrotasks(); //valid if promise handling completed expect(x).toBe(2); expect(y).toBe(3); })); it('Promises fulfilled by tick',fakeAsync((): void => { let x = 1; let y = 2; let dealWithIt = function(p:Promise) { p.then( v => { x = v; Promise.resolve(v).then( v=> {y = v+1; }); }); }; let p = Promise.resolve(y); dealWithIt(p); tick(); //valid if promise handling completed expect(x).toBe(2); expect(y).toBe(3); })); 

Ed entrambi i test passano. Al momento di verificare le aspettative, la promise è stata gestita correttamente.

Ma è garantito ? O ero solo fortunato.

Ci sono dei limiti, tutte le Promesse create nell’ambito di fakeAsync essere ‘licenziate’ chiamando tick o flushMicrotasks .

L’utilizzo congiunto di fakeAsync e tick / flushMicrotasks consente di simulare l’elaborazione asincrona, ma in modo “sincrono”. Pertanto, è garantito che la richiamata specificata nel tuo metodo then sia eseguita prima dell’esecuzione delle tue aspettative.

Dalla documentazione:

  • fakeAsync

Avvolge una funzione da eseguire nella zona fakeAsync:

  • le microtasche vengono eseguite manualmente chiamando flushMicrotasks (),
  • i timer sono sincroni, tick () simula il passaggio del tempo asincrono.

Se ci sono dei timer in sospeso alla fine della funzione, verrà generata un’eccezione.

  • zecca

tick dell’esportazione (millis ?: numero): void

esportato da angular2 / testing definito in angular2 / src / testing / fake_async.ts (riga 84) Simula il passaggio di tempo asincrono per i timer nella zona fakeAsync.

La coda dei microtasks viene svuotata proprio all’inizio di questa funzione e dopo l’esecuzione di ogni richiamo del timer.

  • flushMicrotasks

export flushMicrotasks (): void

Lavare qualsiasi microtask in sospeso.

Ecco il plunkr corrispondente:

Sotto il cappuccio

Infatti la funzione fakeAsync crea una zona dedicata che intercetta l’elaborazione asincrona delle funzioni setTimeout , clearTimeout , setInterval , clearInterval ma sovrascrive anche la funzione scheduleMicrotask . In questo modo, il fakeAsync può controllare completamente l’elaborazione asincrona e simulare l’elaborazione asincrona. Si affida a DelayedFunctionScheduler di Jasmine.

La registrazione di un callback su una promise utilizzando il metodo then accoda immediatamente una microtask richiamando la funzione scheduleMicrotask precedentemente definita nella zona personalizzata. In questo modo questa zona ha la mano su quando eseguire il callback di promise.

La funzione flushMicrotasks semplicemente iterazioni sulle microtasks registrate e le esegue in modo sincrono (incluso il callback precedentemente registrato della promise). Il tick fa lo stesso, ma chiama anche il metodo tick dello schedulatore Jasmine.

Questo articolo potrebbe fornire ulteriori dettagli:

Potresti dare un’occhiata al codice sorgente di fakeAsync :

Quindi sì, come ha spiegato Thierry nella sua risposta fakeAsync consente di testare in modo sincrono la logica di business dietro la gestione delle promesse.

Volevo solo aggiungere che il test per fakeAsync ha anche specifiche per gli scenari relativi alla promise:

 describe('Promise', () => { it('should run asynchronous code', fakeAsync(() => { ... it('should run chained thens', fakeAsync(() => { ... it('should run Promise created in Promise', fakeAsync(() => { 

Ho trovato questi test su: https://github.com/angular/angular/blob/master/packages/core/test/fake_async_spec.ts