How to test a method with multi-http calls

185 Views Asked by At

How do you test the findArtists method with the httpTestingController? So ideally what this service is doing is fetching some artists' data on the first get call but the data returned doesn't have all the data required for displaying in the template. Hence, that's why I am mapping more HTTP calls in the switchMap because those subsequent calls provide the extra data needed on the template. This means I can't use the httpTestingController.expectOne() maybe because on the same service.fetchArtists() I probably am making 5 subsequent calls plus the first that's fetching the incomplete list.

ServiceClass.ts

   public findArtists(searchTerm = ''): Observable<ArtistModel[]> {
    return this.http.get<SongsResponse>(this.resolveUrl(`/search?q=artist:"${ encodeURI(searchTerm) }"`))
      .pipe(
        switchMap(res => {
          const artistObservables = res.map(artistId => this.getArtistDetails(artistId)); //make more http observables here.

          return forkJoin([...artistObservables]);
        })
      );
  }

  public getArtistDetails(artistId: number): Observable<ArtistModel> {
    return this.http.get<ArtistModel>(this.resolveUrl(`/artist/${ artistId }`));
  }

The test code:

  it('should search for artists', fakeAsync(() => {
service.findArtists('searchTerm')
  .subscribe({
    next: artists => {
      expect(artists).toBeTruthy();
      expect(artists.length).toBe(5);
    }
  });

const req = httpTestingController.expectOne('api/search?q=artist:"searchTerm"');
expect(req.request.method).toBe('GET');
pending('No idea how to handle subsequent http calls.');
req.flush({
  data: tracksHelper.generateTracks(5)
});

The error I am getting: enter image description here

1

There are 1 best solutions below

0
On

Like the error says, there are many API requests pending (5).

So what we can do is use the match of httpTestingController.

Try the following:

  it('should search for artists', fakeAsync(() => {
service.findArtists('searchTerm')
  .subscribe({
    next: artists => {
      expect(artists).toBeTruthy();
      expect(artists.length).toBe(5);
    }
  });

const req = httpTestingController.expectOne('api/search?q=artist:"searchTerm"');
expect(req.request.method).toBe('GET');
pending('No idea how to handle subsequent http calls.');
req.flush({
  data: tracksHelper.generateTracks(5)
});

// Let's get all the pending requests as an array
const reqs = httpTestingController.match(request => request.url.includes('api/artist/'));

// Loop through all requests
reqs.forEach(req => {
  expect(req.request.method).toBe('GET');
  req.flush({
    // send whatever you wish here 
  });
});

// verify no pending requests should pass now. You most likely already have 
// this in an afterEach.
  httpTestingController.verify();
});