Jasmine在测试函数内等待异步函数

nip*_*777 3 javascript unit-testing jasmine angular

我正在尝试测试Angular 2组件,它依赖于服务调用来填充数据.但是,这个服务调用promise是在另一个函数内部处理的.

this.data = null; //empty data is defined here.

public getDataMethod(){
    // controller related logic
    privateService.privateMethod(
        (data) => {this.data = data} //the data is populated here
    )
}
Run Code Online (Sandbox Code Playgroud)

我怎么能等待内部函数解决?

我读到我们可以等待承诺以"完成"来解决,但我发现的唯一例子是直接调用承诺.(不是函数内的嵌套promise)

我尝试将done方法传递给函数,它运行良好.

public getDataMethod(done){
    // controller related logic
    privateService.privateMethod(
        (data) => {this.data = data} //the data is populated here
        done(); //Calling done when the promise is resolved. 
    )
}
Run Code Online (Sandbox Code Playgroud)

但是,这确实使得经过测试的代码变得混乱.data在运行测试之前是否有更好的方法等待填充值?

Pau*_*tha 8

这一点在Angular文档测试部分使用异步服务测试组件中进行了解释.你基本上有几个选择.

  1. 使用async包装测试.Angular知道什么时候发生异步任务,因为它使用区域来修补所有异步函数setTimeout.当我们使用时async,Angular将阻止测试完成,直到所有异步任务都不在队列中.

    import { async } from '@angular/core/testing';
    
    it('..', async(() => {
       // any async calls that happen between here
       // will be completed before the test completes
    }))
    
    Run Code Online (Sandbox Code Playgroud)

    另一部分是在我们做出任何断言之前等待异步任务完成.为此,我们可以使用fixture.whenStable()哪个将在异步任务完成之前等待,然后通过承诺通知我们

    it('..', async(() => {
       service.someAsyncTask();
       fixture.whenStable().then(() => {
         expect(...) 
       })
    }))
    
    Run Code Online (Sandbox Code Playgroud)
  2. 另一种选择是使用fakeAsync/tick组合.Angular允许我们通过调用等待异步任务完成tick.这允许我们使测试看起来是同步的

    import { fakeAsync, tick } from '@angular/core/testing';
    
    it('..', fakeAsync(() => {
       service.someAsyncTask();
       tick();
       expect(...)
    }))
    
    Run Code Online (Sandbox Code Playgroud)