fakeAsync 不应该阻止自动订阅完成吗?

Shouldn't fakeAsync prevent automatic subscription completion?

我认为通过使用 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() 调用放入规范中。

我做错了什么?

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

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

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

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 完成。