【问题标题】:Shouldn't fakeAsync prevent automatic subscription completion?fakeAsync 不应该阻止自动订阅完成吗?
【发布时间】:2021-07-30 01:57:09
【问题描述】:

我认为通过使用 fakeAsync 包装器,我的测试不会自动运行订阅,并且我会通过手动调用 tick 来控制该部分,但情况似乎并非如此。例如,使用这种方法:

foo(): void {
    of([1, 2, 3]).subscribe({
        next: () => {
            console.info('Subscription completed.')
            this.value = true
        },
        error: (err: unknown) => console.error('error called')
    })
}

并使用此规范进行测试:

it('should foo', fakeAsync(() => {
    component.foo()
    expect(component.value).toBeFalse()
}))

我看到订阅完成消息打印,因此预期失败。我以为 foo 方法会被调用,但是直到我在规范中添加了 tick() 调用后订阅才会完成。

我做错了什么?

【问题讨论】:

    标签: jasmine angular-unit-test


    【解决方案1】:

    滴答只是控制时间流逝的方式。来自 Angular 文档。 If you omit the tickOptions parameter (tick(100))), then tickOptions defaults to {processNewMacroTasksSynchronously: true}.

    https://angular.io/api/core/testing/tick

    【讨论】:

    • 但是当我进行第一次期望检查时,我根本没有打电话给tick。为什么订阅已被调用?
    【解决方案2】:

    您认为所有可观察对象都是异步的假设是错误的。

    Observables 可以是异步的也可以是同步的,具体取决于底层实现。换句话说,如果源是同步的,则反应流是同步的,除非您明确将它们设为异步。

    一些例子:

    //Synchronous
    of(1,2)
      .subscribe(console.log);
    
    //asynchronous because of async source
    interval(1000)
      .subscribe(console.log);
    
    //aynchronous because one stream is async (interval)
    of(1,2)
      .pipe(
        mergeMap(x => interval(1000).pipe(take(2)))
      )
      .subscribe(console.log);
    
    //async because we make it async
    of(1,2, asyncScheduler)
      .subscribe(console.log);
    

    TLDR:因为of([1, 2, 3]) 是一个异步源,您将无法控制它何时以fakeAsync 完成。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-10
      • 2021-06-19
      • 2020-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 1970-01-01
      相关资源
      最近更新 更多