HttpClient 拦截器重试单元测试(预期没有打开请求,找到 1 个)

HttpClient interceptor retry unit testing (Expected no open requests, found 1)

我有一个简单的 HttpClient 拦截器,它只重试失败的请求一定次数。现在,我正在尝试为其编写单元测试,但不知何故我最终得到了一个未完成的请求。我试过将测试包装在 fakeAsync 中或使用 done 但它似乎没有帮助。现在我没主意了。

我得到的错误是: Error: Expected no open requests, found 1: GET mock/url

我错过了什么?

server-error.interceptor.ts

import { Injectable } from '@angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs';
import { retry } from 'rxjs/operators';
import { ConfigService } from '@app/shared/services/config.service';

/**
 * Http error interceptor class
 */

@Injectable()
export class ServerErrorInterceptor implements HttpInterceptor {
  constructor(private configService: ConfigService) {}

  /**
   * Intercepts failed requests and retries set amount of times before throwing an error
   *
   * @param request  HTTP request
   * @param next  HTTP handler
   *
   * @returns Observable of Http event
   */
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(request).pipe(retry(this.configService.config.httpRetryCount));
  }
}

server-error.interceptor.spec.ts

import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController, TestRequest } from '@angular/common/http/testing';
import { HTTP_INTERCEPTORS, HttpClient, HttpErrorResponse } from '@angular/common/http';

import { ServerErrorInterceptor } from '@core/interceptors/server-error.interceptor';
import { ConfigService } from '@shared/services/config.service';

const mockUrl = 'mock/url';
const mockHttpRetryCount = 5;
const mockErrorText = 'Mock error!';

const mockConfigService: object = {
  config: jest.fn().mockReturnValue({
    httpRetryCount: mockHttpRetryCount
  })
};

describe('ServerErrorInterceptor', () => {
  let httpClient: HttpClient;
  let httpTestingController: HttpTestingController;
  let interceptor: ServerErrorInterceptor;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [
        ServerErrorInterceptor,
        { provide: ConfigService, useValue: mockConfigService },
        { provide: HTTP_INTERCEPTORS, useClass: ServerErrorInterceptor, multi: true }
      ]
    });

    httpClient = TestBed.get(HttpClient);
    httpTestingController = TestBed.get(HttpTestingController);
    interceptor = TestBed.get(ServerErrorInterceptor);
  });

  afterEach(() => {
    httpTestingController.verify();
  });

  it('should be created', () => {
    expect(interceptor).toBeTruthy();
  });

  it('should retry an errored request set amount of times', (): void => {
    httpClient.get(mockUrl).subscribe(
      null,
      (response: HttpErrorResponse): void => {
        expect(response.status).toEqual(500);
        expect(response.message).toEqual(`Http failure response for ${mockUrl}: 500 Server Error`);
      }
    );

    for (let i = 0; i < mockHttpRetryCount; i += 1) {
      const request: TestRequest = httpTestingController.expectOne(mockUrl);
      request.flush(mockErrorText, { status: 500, statusText: 'Server Error' });
    }
  });
});

实际上我自己找到了答案。我的代码中有 3 个独立的错误:

  1. ConfigService 以错误的方式被嘲笑,并为 httpRetryCount
  2. 返回 undefined
  3. 在所有重试失败后拦截器没有抛出错误。
  4. 应触发测试中的 for 循环 mockHttpRetryCount + 1 以说明所有重试以及最终结果(正或负)