6

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.

Liam
  • 27,717
  • 28
  • 128
  • 190
maxsoulard
  • 291
  • 1
  • 6
  • 17
  • I have similar problem with rxjs streams. `transmitted$.switchMapTo(this.initializePayment).switchMapTo(this.getPaymentUrl)` . these methods are private and make http calls, stream is only public... – Dawid Winiarczyk Dec 27 '17 at 15:29

1 Answers1

6

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();    
}));
Liam
  • 27,717
  • 28
  • 128
  • 190
Michael R.
  • 388
  • 3
  • 9
  • I was able to get some tests working using `waitForAsync` instead, but this seems to work more consistently. The problem is if the function under test makes more than one HTTP request, sequentially -- like looking up a record, then making another lookup based on the first one. In that case you can make the request, tick, expect/verify, tick, etc. – Coderer Nov 26 '20 at 13:34