Angular Karma-Jasmine测试:Spec未等待.then块完成就执行断言
问题根源与解决方案
核心问题:服务实现未等待所有异步操作完成
你的initializeAPI函数虽然用await等待了fetch请求完成,但没有等待data.json().then(...)里的异步解析和赋值操作。data.json()返回的是Promise,直接用.then()的话,这些回调会进入微任务队列,在initializeAPI函数执行完毕后才会触发。这就导致测试中await service.initializeAPI()只等了fetch完成,却没等后续的数据解析和赋值,所以断言时数据还未更新。
方案1:修复服务代码(推荐)
将.then()替换为await,让initializeAPI函数真正等待所有异步步骤完成:
async initializeAPI() { // 第一个API请求 let data = await fetch('//my 1st api call'); const r1 = await data.json(); console.log("then1"); this.CLASSDATA = r1.res.rows; console.log("API read_classdata called"); // 第二个API请求 data = await fetch('//my 2nd api call'); const r2 = await data.json(); console.log("then2"); this.RABILITYDATA = r2.res.rows; // 第三个API请求 data = await fetch('//my 3rd api call'); const r3 = await data.json(); this.PABILITYDATA = r3.res.rows; console.log("then3", r3.res.rows[0], this.PABILITYDATA[0]); console.log("API read_abilitydata called"); }
修改后,initializeAPI会等待所有JSON解析和数据赋值完成再返回,测试中await service.initializeAPI()之后就能直接拿到正确的数据,原测试用例的断言会自动通过。
方案2:不修改服务,调整测试用例
如果暂时无法修改服务代码,可以通过fakeAsync+flushMicrotasks()强制等待所有微任务(即.then()里的回调)执行完毕:
it('should initialize apis for class and ability', fakeAsync(() => { service.CLASSDATA = []; const fetchspy = spyOn(window, 'fetch').and.returnValues( Promise.resolve(classres), Promise.resolve(rabres), Promise.resolve(pabres) ); initspy.and.callThrough(); // 调用初始化函数 service.initializeAPI(); // 刷新所有微任务队列,触发所有.then()回调 flushMicrotasks(); expect(fetchspy).toHaveBeenCalledTimes(3); expect(service.CLASSDATA).toEqual(MOCKCLASSDATA); }));
这种方式能绕过服务的异步缺陷,但仅适合临时测试场景,长期来看还是修复服务代码更可靠——实际业务中也需要确保所有数据加载完成后再执行后续逻辑。
内容的提问来源于stack exchange,提问作者djmcdo
相关产品推荐
相关产品推荐

