【问题标题】:HttpTestingController expectOne not working when actual request is nested within a promise当实际请求嵌套在承诺中时,HttpTestingController expectOne 不起作用
【发布时间】:2019-12-13 19:07:10
【问题描述】:

我正在尝试对从另一个服务获取值(返回 Promise)然后执行 http GET 请求的服务进行单元测试。

我正在使用来自 @angular/common/http/testing 的 HttpTestingController 来模拟 http 请求。这是测试和产品代码:

tested.service.spec.ts

it('should get base url from indexedDb then execute http get request', (async () => {
  fakeParametresService.getBaseUrl.and.returnValue(Promise.resolve({valeur: 'http://host:port'}));

  testedService.get<any>('/endpoint').then((response: any) => {
    expect(response.key).toBe('value');
  });

  await http.expectOne('http://host:port/endpoint').flush({key: 'value'});
  http.verify();    
}));

tested.service.ts

async get<T>(endpoint: string): Promise<T> {
  const baseUrl = await this.parametresService.getBaseUrl();
  return this.http.get<T>(`${baseUrl.valeur}${endpoint}`).toPromise();
}

似乎无法以这种方式模拟嵌套在承诺中的 http 请求。但也许这是我的一个误解。

【问题讨论】:

  • 我对 rxjs 流也有类似的问题。 transmitted$.switchMapTo(this.initializePayment).switchMapTo(this.getPaymentUrl) 。这些方法是私有的并进行 http 调用,流只是公共的......

标签: angular jasmine


【解决方案1】:

对我来说,使用fakeAsync 测试区很有效。那里有 tick() 函数,它会等到所有承诺都得到解决,然后继续你的测试。问题是您无法在 fakeAsync 区域中发出任何 XHR 请求,但使用 HttpClientTestingModule 对我来说效果很好。

it('should get base url from indexedDb then execute http get request', fakeAsync(() => {
  fakeParametresService.getBaseUrl.and.returnValue(Promise.resolve({valeur: 'http://host:port'}));

  testedService.get<any>('/endpoint').then((response: any) => {
    expect(response.key).toBe('value');
  });
  // wait until all Promises are resolved
  tick();
  http.expectOne('http://host:port/endpoint').flush({key: 'value'});
  http.verify();    
}));

【讨论】:

  • 我能够使用waitForAsync 进行一些测试,但这似乎更一致。问题在于,如果被测函数按顺序发出多个 HTTP 请求,例如查找一条记录,然后根据第一个请求进行另一次查找。在这种情况下,您可以提出请求、勾选、期望/验证、勾选等。
最近更新 更多