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

HttpTestingController匹配失败:Promise型HttpInterceptor测试问题

两个拦截器的核心差异

同步与异步触发时机的区别

  • ObservableInterceptor:使用BehaviorSubject时,它会在订阅发生时同步发出当前值(此处为true)。因此mergeMap会立即调用next.handle(request),HTTP请求同步触发,测试代码能立刻捕获到请求。
  • PromiseInterceptor:通过from(Promise.resolve(true))将Promise转为Observable后,即便Promise已resolve,from()会把Promise的结果放入微任务队列,需等当前同步代码执行完毕才会触发mergeMap中的next.handle(request)。测试中调用expectOne时,请求尚未发出,因此出现"未找到匹配请求"的错误。
实现可正常测试的Promise拦截器

拦截器本身的逻辑没有问题,只需调整测试代码的异步时序处理。Angular测试提供fakeAsync和tick()来模拟异步任务执行:

it('works with PromiseInterceptor', fakeAsync(() => {
  TestBed.configureTestingModule({
    imports: [HttpClientTestingModule],
    providers: [
      {
        provide: HTTP_INTERCEPTORS,
        useClass: PromiseInterceptor,
        multi: true,
      },
    ],
  });
  const http = TestBed.inject(HttpClient);
  const httpTestingController = TestBed.inject(HttpTestingController);

  http.get(TEST_API).subscribe(value => console.log(value));
  
  // 触发所有待处理的微任务,让Promise回调执行完成
  tick();
  
  const request = httpTestingController.expectOne(TEST_API);
  expect(request.request).toBeTruthy();
  
  // 完成请求并验证无未处理请求(测试清理步骤)
  request.flush({});
  httpTestingController.verify();
}));
补充说明

如果业务中是调用真实异步函数(比如获取token的Promise),拦截器的写法无需修改,核心是测试时通过fakeAsync和tick()处理微任务异步场景,确保请求触发后再执行断言。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 08:02:17