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
相关产品推荐
相关产品推荐

