Angular测试开关示意调用呼叫0次

发布于 2025-01-27 07:31:40 字数 2000 浏览 4 评论 0原文

在我的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导致问题,但我不知道为什么。我尝试在上面的测试代码上应用flushmicrotask() tick() ,并与fixture.whenstabel()结合使用而无需成功。

任何IDE如何解决这个问题?

我也要感谢解释。

In my Angular component I have this code:

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

And I have this test:

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);
}));

The last expectation fails with this message:

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

I think the switchMap causes the issue, but I don't know why. I tried to apply flushMicrotasks(), tick() on above test code, and combined with fixture.whenStabel() without success.

Any ide how can I solve this issue?

And I would also be grateful for an explanation.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

紅太極 2025-02-03 07:31:41

您必须使用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();
}

You have to use done() instead of fakeAsync. The fakeAsync will wait, but the subscription will not be finished. The done() function will "trigger" the rxjs operators, and you can test the result in a subscibe to the observer.

I think just like this:

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();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文