Angular 测试http侦听器-在侦听器返回之前调用expect

Angular 测试http侦听器-在侦听器返回之前调用expect,angular,rxjs,angular-http-interceptors,Angular,Rxjs,Angular Http Interceptors,我有一个简单的HttpInterceptor,用于设置加载状态。这是密码 @Injectable({ providedIn: 'root', }) export class LoaderHttpInterceptor implements HttpInterceptor { constructor(private _loadingService: LoadingService) {} intercept( req: HttpRequest<any>, n

我有一个简单的
HttpInterceptor
,用于设置加载状态。这是密码

@Injectable({
  providedIn: 'root',
})
export class LoaderHttpInterceptor implements HttpInterceptor {
  constructor(private _loadingService: LoadingService) {}

  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {

    const id = uuid();

    this._loadingService.startLoading(id);

    return next
      .handle(req)
      .pipe(finalize(() => this._loadingService.completeLoading(id)));
  }
}
在最后两个测试中,在拦截器中的
finalize
操作符之前调用了测试中的
expect
语句,我不知道为什么。我的印象是,直到拦截器完成,http调用才会返回

如果我在第二个测试中添加
pipe(delay(1000))
,它将工作,但这是错误的。在第三次测试中这样做没有什么区别

我希望有人能给我解释一下

谢谢。

我想重新(阅读)文档和源代码会有所帮助。我认为测试需要是异步的,因为正常的http请求是异步的,但是
HttpTestingController
是同步发出的。测试需要像这样编写:

    it('should call loader service completeLoading on success', () => {
      const url = faker.internet.url();

      httpClient.get(url, { responseType: 'text' }).subscribe();

      controller.expectOne(url).flush({}, { status: 200, statusText: ''} );
      controller.verify();
      expect(mockLoadingService.completeLoading).toBeCalledTimes(1);
    });

为什么你认为
下一步
错误
处理程序应该在
完成
之后执行?@yurzui-你知道为什么之前执行它们,因为这就是我要问的吗?拦截器应该转换流,那么为什么在返回http响应后调用
finalize
,或者我完全误解了这一点?因为finalize是在observable完成或出错时调用的。好吧,我想我只是误解了http请求管道的工作方式。在深入研究Angular源代码之后,发现拦截器在http请求的Observable中运行,因此在http请求Observable完成之前,
finalize
不会被调用。
    it('should call loader service completeLoading on success', () => {
      const url = faker.internet.url();

      httpClient.get(url, { responseType: 'text' }).subscribe();

      controller.expectOne(url).flush({}, { status: 200, statusText: ''} );
      controller.verify();
      expect(mockLoadingService.completeLoading).toBeCalledTimes(1);
    });