首页 > 解决方案 > 如何测试 Observable 不会在包含异步逻辑的 Angular 组件中发出

问题描述

假设我有一个 Angular 组件,它将 Observable 定义myObs$为其属性之一。

在一项测试中,给定某些条件,我想测试myObs$不通知。在逻辑中存在一些延迟,因此测试必须是异步的。

我正在使用茉莉花

到目前为止,我已经能够制定这个解决方案:

it('async test', done => {
    let dataEmitted;
    myObs$
    .pipe(
      tap(data => dataEmitted = data),
    )
    .subscribe();
    setTimeout(() => {
      if (dataEmitted) {
        done.fail('should not emit');
      } else {
        done();
      }
    }, 1000);
  });

但我对此并不满意。我必须依靠setTimeout执行检查并调用该done函数。

有关如何正确执行此类测试的任何建议?同步解决方案不起作用,因为逻辑中存在内在的异步性。

标签: angularjasminerxjsangular-test

解决方案


如果是基于setTimeout/debounceTime 等的异步逻辑,你可以使用fakeAsync()函数来测试它,这个函数会将所有这些异步操作替换为同步操作,因此可以测试你的逻辑,因为它是同步的。您也可以使用tick()跳过 VM 轮次(它也会同步发生!)。使用此解决方案,您将拥有漂亮、干净、快速且可靠的单元测试。

代码示例

it('asynch test', fakeAsync(() => {
    let dataEmitted;
    myObs$.subscribe(data => dataEmitted = data);

    tick(1000);
    
    expect(dataEmitted).toBeUndefined();
}));

我建议您也检查负面情况,例如tick(2000)并检查它是否发出值。希望有帮助。


推荐阅读