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

Angular 10幂等请求重试拦截器测试异常求助:修改逻辑后测试未按预期失败

问题出在你的测试用例上,而非拦截器逻辑

你的拦截器代码是正常工作的(从你打印的日志也能看出来),测试没有按预期失败的核心原因是测试用例没有正确验证请求的重试行为,具体来说有这几个问题:

1. 没有验证请求数量,也没检查未处理请求

当拦截器对POST请求重试时,会发送第二次请求,但你的测试只调用了一次httpTestingController.expectOne()处理第一次请求,第二次请求会留在HttpTestingController的请求队列中。由于你没有调用httpTestingController.verify()(或expectNoMoreRequests()),测试结束时不会检查是否有未处理的请求,自然不会触发失败。

2. 订阅未处理错误回调

你的订阅只写了成功回调:

http.post('/api/resource', {}).subscribe(response => expect(response).toBeTruthy());

当两次请求都失败后,订阅会抛出未捕获的错误,但在fakeAsync环境下,这个错误可能没有被测试框架及时捕捉到,导致测试看起来“通过”,但实际上存在未处理的异常。

修正后的测试用例

下面是调整后的测试代码,能正确验证POST请求是否被重试:

it('should not retry POSTs', fakeAsync(() => {
  let errorOccurred = false;
  let errorCount = 0;

  // 同时处理成功和错误回调,确保错误被捕获
  http.post('/api/resource', {}).subscribe(
    () => fail('POST request should not succeed'),
    (error) => {
      errorOccurred = true;
      errorCount++;
      // 预期只会触发一次错误(不重试)
      expect(errorCount).toBe(1);
    }
  );

  // 捕获并处理第一次POST请求
  const firstReq = httpTestingController.expectOne({ method: 'POST', url: '/api/resource' });
  firstReq.error(new ErrorEvent('network error', { message: 'bad request' }), { status: 400 });

  tick();

  // 关键:验证没有更多请求被发送(即拦截器未重试)
  httpTestingController.verify();
  
  // 确保错误确实被触发
  expect(errorOccurred).toBe(true);
}));

为什么这样能生效?

  • 我们显式处理了错误回调,统计错误触发次数,如果拦截器重试,errorCount会变成2,expect(errorCount).toBe(1)会直接让测试失败。
  • httpTestingController.verify()会检查所有已发送的请求是否都被处理,如果拦截器发送了第二次请求,这里会抛出“存在未处理请求”的错误,直接让测试失败。

现在当你把IDEMPOTENT_METHODS设为['POST']时,这个测试会按预期失败,符合你的测试目的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 10:42:39