如何测试带延迟的递归HTTP轮询超时场景?
解决轮询超时场景的测试问题
我来帮你搞定这个超时场景的测试难题~你遇到的expected no open requests found 1错误,本质是超时场景需要触发多次轮询请求,但之前的测试只处理了单次请求,导致还有未完成的HTTP请求挂着,最终触发了未处理请求的校验错误。
核心思路
你的poll函数是递归实现的:每次返回Ongoing状态时,会延迟retryTime后再次发起GET请求,直到重试次数耗尽才抛出超时错误。所以测试需要模拟以下流程:
- 触发初始的POST请求,获取actionId。
- 循环模拟
config.retryCount + 1次GET请求(因为初始retryCount是配置值,每次调用poll会先发起请求再减计数,直到计数为-1时抛出错误)。 - 每次请求后触发
tick(config.retryTime)来模拟延迟,触发下一轮轮询。 - 最终验证超时错误是否正确抛出,且所有HTTP请求都被处理完毕。
完整测试用例代码
it('should throw timeout error when action stays ongoing beyond retry limit', fakeAsync(() => { // 准备Mock数据:所有轮询请求都返回Ongoing状态 const mockOngoingResponse = { action: { id: mockActionId, state: 'Ongoing' } }; let timeoutErrorTriggered = false; // 触发doAction并订阅结果,捕获超时错误 service.doAction(mockContent).subscribe( () => fail('Expected timeout error, but received success response'), (err) => { expect(err).toEqual('Action Timed Out'); timeoutErrorTriggered = true; } ); // 处理第一个POST请求(获取actionId的请求) const postCall = httpTestingController.expectOne(url1); expect(postCall.request.method).toEqual('POST'); postCall.flush(mockPostActionResponse); // 处理所有轮询的GET请求:总次数为 config.retryCount + 1 const totalPollAttempts = config.retryCount + 1; for (let i = 0; i < totalPollAttempts; i++) { // 模拟轮询的延迟时间 tick(config.retryTime); // 匹配当前的GET请求(多次请求URL相同,用match获取所有匹配项) const allGetCalls = httpTestingController.match(`${url2}/${mockActionId}`); const currentGetCall = allGetCalls[i]; expect(currentGetCall.request.method).toEqual('GET'); // 返回Ongoing状态,触发下一轮轮询(直到最后一次) currentGetCall.flush(mockOngoingResponse); } // 验证超时错误是否正确触发 expect(timeoutErrorTriggered).toBeTrue(); // 确保所有HTTP请求都被处理完毕,避免未处理请求的错误 httpTestingController.verify(); }));
关键细节说明
- 为什么用
match而不是expectOne:因为轮询请求的URL完全相同,expectOne只能匹配单次请求,而match会返回所有匹配该URL的请求数组,我们可以按顺序逐个处理。 - 循环次数的计算:初始
retryCount是config.retryCount,每次进入poll函数后会先发起GET请求,再将计数减1,直到计数小于0时抛出错误。所以总共有config.retryCount + 1次GET请求。 tick的时机:每次处理完GET请求后,必须用tick(config.retryTime)来模拟time(config.retryTime)的延迟,这样才能触发下一轮的轮询调用。- 最后的
verify():必须调用这个方法来确保所有HTTP请求都被flush,彻底解决你遇到的“未处理请求”错误。
内容的提问来源于stack exchange,提问作者PMO1948
相关产品推荐
相关产品推荐

