Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HttpTestingController expectOne not working when actual request is nested within a promise

I am trying to unit test a service which gets a value from another service (returns a Promise) then execute http GET request.

I am using HttpTestingController from @angular/common/http/testing to mock the http request. Here is the test and prod code :

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();
}

It seems that a http request nested within a promise cannot be mocked that way. But maybe it's a misunderstanding from me.

like image 259
maxsoulard Avatar asked Nov 02 '17 08:11

maxsoulard


1 Answers

For me it worked, to use the fakeAsync testzone. There you have the tick() function which waits until all promises are resolved and continues your test afterwards. The Problem is that you can't make any XHR request in the fakeAsync Zone, but it worked fine for me with the 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();    
}));
like image 131
Michael R. Avatar answered Sep 28 '22 00:09

Michael R.