Angular 17链式Promise单元测试失败,如何修复?
Angular 17链式Promise单元测试修复方案
问题原因
测试断言失败是因为原生Response对象的json()方法返回的Promise未被Zone.js的fakeAsync环境正确跟踪,导致flush()/tick()无法触发后续的then回调;另外代码中Promise.resolve(mockItem.promise)属于多余嵌套,可简化。
解决方案
方案一:模拟Response对象,确保Promise被Zone.js跟踪
修改测试代码,手动模拟Response的json()方法,返回受控的Promise:
it(`nested promise testing`, fakeAsync(() => { let item = ''; // 模拟Response对象,自定义json方法返回可被Zone跟踪的Promise const mockResponse = { json: () => Promise.resolve({ foo: 'bar' }) } as unknown as Response; const mockItem = { promise: Promise.resolve(mockResponse), }; mockItem.promise .then((response) => response.json()) .then((data) => { item = data.foo; }); flushMicrotasks(); // 精准处理所有待执行的微任务 expect(item).toEqual('bar'); }));
方案二:改用async/await测试语法
直接使用async/await替代fakeAsync,让测试自动等待异步操作完成:
it(`nested promise testing`, async () => { let item = ''; const mockItem = { promise: Promise.resolve(new Response(JSON.stringify({ foo: 'bar' }))), }; await mockItem.promise .then((response) => response.json()) .then((data) => { item = data.foo; }); expect(item).toEqual('bar'); });
说明
- 方案一通过模拟原生对象,避免了测试环境对浏览器API的依赖,确保Zone.js能正确捕获异步任务;
flushMicrotasks()专门处理微任务,比flush()更贴合Promise场景。 - 方案二的
async/await语法更直观,无需手动管理任务队列,适合大多数异步测试场景。
内容的提问来源于stack exchange,提问作者Jyoti Sahu
相关产品推荐
相关产品推荐

