Does fakeAsync guarantee promise completion after tick/flushMicroservice

后端 未结 2 1246
日久生厌
日久生厌 2020-11-30 12:46

Main issue is how to test that expected actions were performed once a Promise was completed, for example to test if a component correctly updates its states after receiving

相关标签:
2条回答
  • 2020-11-30 13:07

    Using together fakeAsync and tick / flushMicrotasks allows you to simulate asynchronous processing but in a "synchronous" way. So it's guaranteed that the callback you specified in your then method is executed before executed your expectations.

    From the documentation:

    • fakeAsync

    Wraps a function to be executed in the fakeAsync zone:

    • microtasks are manually executed by calling flushMicrotasks(),
    • timers are synchronous, tick() simulates the asynchronous passage of time.

    If there are any pending timers at the end of the function, an exception will be thrown.

    • tick

    export tick(millis?: number) : void

    exported from angular2/testing defined in angular2/src/testing/fake_async.ts (line 84) Simulates the asynchronous passage of time for the timers in the fakeAsync zone.

    The microtasks queue is drained at the very start of this function and after any timer callback has been executed.

    • flushMicrotasks

    export flushMicrotasks() : void

    Flush any pending microtasks.

    Here is the corresponding plunkr:

    • https://plnkr.co/edit/ARGGaY?p=preview

    Under the hood

    In fact the fakeAsync function creates a dedicated zone that intercepts asynchronous processing of functions setTimeout, clearTimeout, setInterval, clearInterval but also override the scheduleMicrotask function. This way the fakeAsync can completely control asynchronous processing and simulate asynchronous processing. It relies on the DelayedFunctionScheduler from Jasmine.

    Registering a callback on a promise using the then method immediately queues a microtask by calling the scheduleMicrotask function previously defined in the custom zone. This way this zone has the hand on when to execute the promise callback.

    The flushMicrotasks function simply iterates over the registered microtasks and execute them synchronously (included the previously registered callback of the promise). The tick does the same but calls in addition the tick method of the Jasmine scheduler.

    This article could give more details:

    • https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/

    You could have a look at the source code of the fakeAsync:

    • https://github.com/angular/angular/blob/master/modules/angular2/src/testing/fake_async.ts#L34
    0 讨论(0)
  • 2020-11-30 13:26

    So yes, as Thierry explained in his answer fakeAsync allows testing synchronously the business logic behind handling promises.

    I just wanted to add, that the test for fakeAsync have even specs for promise related scenarios:

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

    I found those tests at: https://github.com/angular/angular/blob/master/packages/core/test/fake_async_spec.ts

    0 讨论(0)
提交回复
热议问题