【问题标题】:How to test RxJS switchMap with Jasmine in Angular?如何在 Angular 中使用 Jasmine 测试 RxJS switchMap?
【发布时间】:2022-01-16 11:45:10
【问题描述】:

在我的 Angular 项目中,我的一个组件中有这段代码:

  delete(post: PostInterface): void {
    const delete$ = this.appDataService.proxy
      .delete(post, this.paginate)
      .pipe(switchMap(() => this.loadDatas()));

    this.subscriptions.add(
      this.appDataService.start(delete$, 'delete').subscribe()
    );
  }

在我的规范文件中:

describe('PostListComponent', () => {
  let component: PostListComponent;
  let fixture: ComponentFixture<PostListComponent>;
  let debugElement: DebugElement;

  beforeEach(async () => {

    await TestBed.configureTestingModule({
      // ...
    })
    .compileComponents()
    .then(() => {
      fixture = TestBed.createComponent(PostListComponent);
      component = fixture.componentInstance;
      debugElement = fixture.debugElement;

      fixture.detectChanges();
    });
  });

  describe('functions', () => {
    it('should be delete with proxy.delete() and reload datas', fakeAsync(() => {
      spyOn(component, 'loadDatas');

      component.delete(1);

      flush();

      expect(component.loadDatas).toHaveBeenCalledTimes(1);
    }));
  });
});

在实际环境中switchMap 工作正常,但在测试中失败并显示以下消息:

PostListComponent > functions > should be delete with proxy.delete() and reload datas

Expected spy loadDatas to have been called once. It was called 0 times.

为什么我的测试中没有运行switchMap?有什么想法吗?

【问题讨论】:

标签: angular rxjs jasmine angular-test switchmap


【解决方案1】:

测试没有按预期工作的原因可能在于您没有subscribe Observable。

订阅启动流,即触发执行嵌入在 Observable 链中的任何代码。

所以,你可能想试试这个版本的测试,看看情况是否有所改善

 describe('functions', () => {
    it('should be delete with proxy.delete() and reload datas', (done) => {
      spyOn(component, 'loadDatas');

      component.delete(1).subscribe({
        next: err => done(err),
        complete: () => {
           expect(component.loadDatas).toHaveBeenCalledTimes(1);
           done();
        }
      });

      flush();

    });
  });

如您所见,我没有使用 fakeAsync,我假设 delete 实际上已被执行。

【讨论】:

  • component.delete() 是无效的。不是可观察的。在这个函数中,订阅就在那里。
  • 再次阅读问题后,我看到delete 返回了一个空白。同时我想知道this.appDataService.start(delete$, 'delete').subscribe() 是否真的触发了一些异步逻辑。如果此代码异步执行,则expect 逻辑可能在异步逻辑完成之前执行,因此在loadDatas 执行之前。
  • 是的,但是我该如何解决这个问题?需要重新构建组件代码以使其可测试,还是有其他方法可以以这种形式对其进行测试?
  • 我会将代码移动到外部服务,通过依赖注入传递给组件,因此组件只需要以某种方法订阅或使用async 管道。另一方面,该服务是一个更简单的 Typscript 类,您可以使用我的回复中显示的技术对其进行测试
  • 这听起来像是对代码的重构,而不是 switchMap 问题的解决方案。
猜你喜欢
  • 2020-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-13
  • 2018-02-22
  • 2019-05-01
  • 2021-11-25
相关资源
最近更新 更多