Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
518 views
in Technique[技术] by (71.8m points)

angular - Does fakeAsync guarantee promise completion after tick/flushMicroservice

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 some remote content.

In the specs below, the dealWithIt() simulates a logic performed in response to a completed promise (it updates variable and trigger "another async event").

it('Promises fulfilled by flushMicrotasks',fakeAsync((): void => {

    let x = 1;
    let y = 2;

    let dealWithIt = function(p:Promise<number>) {
        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<number>) {
        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);

}));

And both tests pass. At the time of checking expectations the promise was dealt with correctly.

But, is it guaranteed? Or was I just lucky.

Are there any limitations, will all Promises created in the scope of fakeAsync be 'fired' by calling tick or flushMicrotasks.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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:

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:

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...