Angular 测试 switchMap 调用调用 0 次

Angular testing switchMap call called 0 times

在我的 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()
    );
  }

我有这个测试:

beforeEach(async () => {
  loadDatasSpy = spyOn(component, 'loadDatas').and.returnValue(of(paginate));
});

it('should call proxy.delete with model on call delete', fakeAsync(() => {
  loadDatasSpy.calls.reset();

  const id = 1;
  const post: PostInterface = new Post().init({id});

  const proxySpy = jasmine.createSpyObj('ProxyService', ['delete']);
  proxySpy.delete.and.returnValue(of(id));

  const appDataServiceSpy = jasmine.createSpyObj('AppDataService', ['proxy', 'start']);
  appDataServiceSpy.start.and.returnValue(of(id));
  appDataServiceSpy.proxy = proxySpy;

  component.appDataService = appDataServiceSpy;

  component.delete(post);

  flush();

  // ✔️ this expectation is passes
  expect(component.appDataService.proxy.delete)
    .withContext('appDataService.proxy.delete')
    .toHaveBeenCalledTimes(1);

  // ✔️ this expectation is passes
  expect(component.appDataService.proxy.delete)
    .withContext('appDataService.proxy.delete')
    .toHaveBeenCalledWith(post, component.paginate);

  // ✔️ this expectation is passes
  expect(component.appDataService.start)
    .withContext('appDataService.start')
    .toHaveBeenCalledTimes(1);

  // ❌ this expectation is fail
  expect(component.loadDatas).toHaveBeenCalledTimes(1);
}));

最后的期望失败并显示此消息:

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

我认为 switchMap 导致了这个问题,但我不知道为什么。我尝试在上面的测试代码上应用 flushMicrotasks()tick(),并与 fixture.whenStabel() 结合但没有成功。

任何 ide 我该如何解决这个问题?

我也将不胜感激。

您必须使用 done() 而不是 fakeAsync。 fakeAsync 会等待,但订阅不会完成。 done() 函数将“触发”rxjs 运算符,您可以在订阅观察者中测试结果。

我是这样想的:

it('should call proxy.delete with model on call delete', (done) => {
  ...
  component.delete(post);

  component.appDataService.start.subscribe(() => {
    expect(component.appDataService.proxy.delete)
      .withContext('appDataService.proxy.delete')
      .toHaveBeenCalledTimes(1);
    ...
    expect(component.loadDatas).toHaveBeenCalledTimes(1);
  }

  done();
}