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

Angular17迁移后fakeAsync任务需resetFakeAsyncZone才执行的问题

Angular 14→17 + Jest 27→29迁移:fakeAsync测试异步任务延迟触发问题

将Angular项目从v14迁移至v17,同时把Jest从v27升级到v29后,项目运行无控制台错误或警告,但Jest测试出现异常:使用fakeAsync包裹测试时,部分异步任务需在expect断言失败、Angular的resetFakeAsyncZone执行后才会运行——尽管已经添加了必要的flush/tick调用,且该测试此前可正常通过,断点显示数据正常但触发时机晚于断言。

失败测试示例

it('should call Update on submit if shouldUpdate is true', fakeAsync(() => {
  // arrange
  comp.shouldUpdate = true;
  comp.CanAlter = true;
  jest.spyOn(connectionResource, 'Update').mockImplementation((c) => {
     return Promise.resolve({ ...c, Id: connection.Id, Children: [] } as ApiConnection);
  });
  let onSubSpy = jest.spyOn(comp.onSubmit, 'emit');

  // act
  comp.ngOnChanges();
  flush();
  fixture.detectChanges();

  let result = { ...comp.form.getRawValue(), ParentId: probe.Id };
  let submitButton = fixture.debugElement.query(By.css('button[type="submit"]'));
  submitButton.nativeElement.click();
  flush();

  // assert
  expect(connectionResource.Update).toHaveBeenCalledWith(result, connection.Id);
  let cached = coreCache.SearchMonitorableTree(coreCache.PayloadCache.Monitorables[0], 'Id', connection.Id)[0];
  expect(onSubSpy).toHaveBeenCalledWith(cached); // 此断言失败,之后被监听函数才触发
}));

已尝试方案

  • 将断言改为toHaveBeenCalled()验证,仍显示未调用,断言后才触发
  • 使用jest.useFakeTimers(),无效果
  • 添加tick()和flushMicrotasks(),问题未解决
  • 调用resetFakeAsyncZone(),无效

参考资源

  • 问题演示GIF
  • Angular官方14.0至17.0版本更新指南
  • Jest官方变更日志

内容的提问来源于stack exchange,提问作者IMeyers20

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 22:40:01