在tick / flushMicroservice之后,fakeAsync是否保证承诺完成

时间:2016-03-14 14:29:22

标签: angular

主要问题是如何测试Promise完成后执行的预期操作,例如测试组件在收到某些远程内容后是否正确更新其状态。

在下面的规范中,dealWithIt()模拟为响应完成的promise而执行的逻辑(它更新变量并触发“另一个异步事件”)。

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);

}));

两个测试都通过了。在检查期望时,承诺得到了正确处理。

但是,是否有保障?或者我只是幸运。

是否存在任何限制,通过调用tickflushMicrotasks,可以“触发”在fakeAsync范围内创建的所有Promise。

2 个答案:

答案 0 :(得分:16)

同时使用fakeAsynctick / flushMicrotasks可以让您以“同步”方式模拟异步处理。因此,保证您在then方法中指定的回调在执行期望之前执行。

来自文档:

  • fakeAsync
  

包装要在fakeAsync区域中执行的函数:

     
      通过调用flushMicrotasks(),手动执行
  • 微任务   
  • 计时器是同步的,tick()模拟异步的时间流逝。
  •   
     

如果函数末尾有任何挂起的计时器,则会抛出异常。

  

导出刻度(毫秒?:数字):无效

     

从angular2 / src / testing / fake_async.ts中定义的angular2 / testing导出(第84行)   模拟fakeAsync区域中定时器的异步时间流逝。

     

微任务队列在此函数开始时以及执行任何计时器回调后都会耗尽。

  • flushMicrotasks
  

导出flushMicrotasks():void

     

刷新任何待处理的微任务。

这是相应的plunkr:

引擎盖

实际上fakeAsync函数创建了一个专用区域,用于拦截函数setTimeoutclearTimeoutsetIntervalclearInterval的异步处理,但也覆盖{ {1}}功能。这样scheduleMicrotask就可以完全控制异步处理并模拟异步处理。它依赖于Jasmine的fakeAsync

使用DelayedFunctionScheduler方法在promise上注册回调会立即通过调用先前在自定义区域中定义的then函数对微任务进行排队。这样,该区域可以在何时执行promise回调。

scheduleMicrotask函数简单地迭代已注册的微任务并同步执行它们(包括先前注册的promise的回调)。 flushMicrotasks执行相同的操作,但另外调用了Jasmine调度程序的tick方法。

本文可以提供更多详细信息:

您可以查看tick的源代码:

答案 1 :(得分:1)

所以是的,正如蒂埃里在答案中解释的那样,fakeAsync允许同步测试处理承诺背后的业务逻辑。

我只是想补充一点,对于fakeAsync的测试甚至还有与promise有关的规范:

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

我在https://github.com/angular/angular/blob/master/packages/core/test/fake_async_spec.ts

找到了这些测试