HttpTestingController.expectOne 看不到我的请求,但是在afterEach()方法中打开了

HttpTestingController.expectOne can't see my request, but it is open in afterEach() method

我正在编写一个单元测试来测试调用 rest 的服务 API。 expectOne() 找不到我的请求:预期有一个符合条件 "Match URL: http://localhost:5000/api/v1.0/stat/estimation-graph" 的请求,找到 none.

我尝试了 expectOne() 的不同重载,例如:

httpMock.expectOne(url)
httpMock.expectOne({method: 'GET', url: url})
httpMock.expectOne(res => res.method === 'GET' && res.url === url)

此外,我尝试更改 URL 以使其包含参数 ('http://localhost:5000/api/v1.0/stat/estimation-graph?battleCount=100&winCount=50'),但没有成功。

最后,我打开了一个带有 Karma 测试结果的 Chrome 控制台,我发现由于 CORS 策略,我的 API 无法被调用。我也修复了。

我的.spec.ts文件:


// imports..

describe('StatProviderService', () => {
    let injector: Injector;
    let httpMock: HttpTestingController;
    let statService: StatProviderService;
    beforeEach(() => 
    {
        injector = TestBed.configureTestingModule({
            imports: [
                HttpClientModule,
                HttpClientTestingModule,
            ],
            providers: [
                StatProviderService,
            ],
        });
        httpMock = injector.get(HttpTestingController);
        statService = injector.get(StatProviderService);
    });

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

    it('should work', () => {
        let response;
        let url = 'http://localhost:5000/api/v1.0/stat/estimation-graph';

        statService.getEstimationGraphData( 100, 50 )
          .subscribe(res => {
            response = res;
          });

        const req = httpMock.expectOne(url);
        req.flush(response);
    });
});

我的服务class:


// imports...

@Injectable({
    providedIn: 'root'
})
export class StatProviderService {
    // private variables

    constructor(
        private http: HttpClient
    ) { }

    private baseApiUrl(endpoint?: string) {
        return `${this.env.apiUrl}/${this.apiVer}/${endpoint}`;
    }

    getEstimationGraphData(battlecount: number, winCount: number): Observable<IEstimationGraphPoint[]> {
        return this.http.get<IEstimationGraphPoint[]>(`${this.baseApiUrl(this.graphDataEndpoint)}/?battleCount=${battlecount}&winCount=${winCount}`);
    }
}

Karma 结果 window 告诉我它找不到打开的请求:

Error: Expected one matching request for criteria "Match URL: http://localhost:5000/api/v1.0/stat/estimation-graph", found none.

ButafterEach()[=48= 添加 httpMock.verify() 之后] 我得到了下一个错误:

Error: Expected no open requests, found 1: GET http://localhost:5000/api/v1.0/stat/estimation-graph/

看来请求已调用,但比预期晚了。据我订阅 getEstimationGraphData() 应该是同步调用吧?

由于您在服务中使用 URL 附加参数,因此 HttpTestingController 期望测试 URL 也包含参数。不要在您的服务中使用参数创建 URL,而是将它们作为 HttpParams.

传递
getEstimationGraphData(battlecount: number, winCount: number): Observable<IEstimationGraphPoint[]> {
  return this.http.get<IEstimationGraphPoint[]>(this.baseApiUrl(this.graphDataEndpoint), {
    params: {
      battleCount: battlecount.toString(),
      winCount: winCount.toString()
    }
  });
}

现在,在您的规范文件中,您需要使用自定义函数来检查 url。使用以下代码测试 url:

const req = httpMock.expectOne((request: HttpRequest<any>) => {
  return request.url === url;
});

request.url 将包含没有参数的 url。实际的 URL 和参数将在 request.urlWithParams 中,以防万一您还需要检查参数。

您可能还需要从规范文件中删除 HttpClientModule。你只需要 HttpClientTestingModule.