You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 18 + Jest 29单元测试中router.navigate被误判为调用两次的问题求助

Angular 18 + Jest 29单元测试中router.navigate被误判为调用两次的问题求助

我最近在给Angular 18组件的一个方法写单元测试时遇到了个头疼的问题:组件代码里明明只在HTTP请求成功后调用了一次router.navigate,但测试却提示这个方法被调用了两次,导致断言失败。

先给大家看组件里的目标方法(已经精简了无关代码):

requestInformation_click() {
  this.showCommentError = !this.comment; // 转成布尔值
  if (this.comment) {
    this.accountsService.requestMoreInformation(this.requestId, this.comment).subscribe(
      response => {
        this.router.navigate(
          [`/list-account-requests/${this.requestId}`], 
          { state: { feedback: '\'Additional info needed\' request sent' } }
        );
      },
    );
  }
}

接下来是我的测试配置和对应测试用例:

// 模拟依赖对象
mockRouter = { navigate: jest.fn() };
mockAccountsService = { requestMoreInformation: jest.fn(() => of()), }

await TestBed.configureTestingModule({
  // 其他配置项
  providers:[
    { provide: AccountsService, useValue: mockAccountsService },
    { provide: Router, useValue: mockRouter },
  ],
})
.compileComponents();

it('should route to `list-account-requests/abc123` when requestMoreInformation is successful', () => {
  component.comment = 'this is a call';
  route.snapshot.params.requestId = 'abc123';
  const detailsSpy = jest.spyOn(mockAccountsService, 'requestMoreInformation').mockReturnValue(of({ success: true, }));
  
  component.requestInformation_click();
  
  expect(mockRouter.navigate).toHaveBeenCalledWith(['/list-account-requests/abc123']);
});

VS Code里抛出的测试错误信息如下:

NewAccountRequestDetailsComponent > should route to list-account-requests/abc123 when requestMoreInformation is successful

Error: expect(jest.fn()).toHaveBeenCalledWith(...expected)
Expected: ["/list-account-requests/abc123"]
Received 1 Array [

  • "/list-account-requests/abc123",
  • "/list-account-requests",
    ], 2 Array [
  • "/list-account-requests/abc123",
  • "/list-account-requests/undefined",
    ],
  • {"state": {"feedback": "'Additional info needed' request sent"}},
    Number of calls: 2

我已经尝试了几种排查方法,都没能解决问题:

  • 把断言改成包含state参数的完整调用,结果还是提示调用了两次;
  • 在afterEach钩子中调用jest.clearAllMocks(),没有任何效果;
  • 怀疑是其他测试用例的影响,把所有涉及router测试的用例都注释掉,重新运行还是一样的错误;
  • 我甚至临时加了expect(mockRouter.navigate).toHaveBeenCalledTimes(2),这个断言居然能通过,说明Jest确实认为它被调用了两次,但我组件里明明只写了一次调用逻辑啊!

另外,我在其他测试用例里测试router.navigate是完全正常的,比如下面这个用例就能顺利通过:

it('should route to `list-account-requests` when requestId is null or undefined', () => {
  route.snapshot.params.requestId = undefined;
  component.ngOnInit();
  expect(mockRouter.navigate).toHaveBeenCalledWith(['/list-account-requests']);
  expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
});

有没有大佬能帮我分析下,到底为什么这个测试会认为router.navigate被调用了两次呢?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 14:39:31