Testing an Http service that performs multiple calls and returns an observable without matching responses

I have a data service that retrieves data from a server and makes several queries, which then return an array of observables. I want to check the data.

What I tried to do is in mockrespone, which I sent an array that contains two observables, I don’t know if it is correct to check the data.

But the tests fail, especially the last three tests in the asynchronization test block

Important: I want to check that when setting charId to false and comicsId to false by calling the method, subscribing to the observable that it returns, after you mocked http, you return an array containing two expected answers. Same thing with 4 expected answer if charId is true. The same for 6 expected answers when comicsId is true

// service that retrieves data

getChar(): Observable<any> { const Observables = []; Observables.push(this.http.get('https://gateway.marvel.com:443/v1/public/characters?apikey')); Observables.push(this.http.get('https://gateway.marvel.com:443/v1/public/comics?apikey')); if (this.charId) { Observables.push(this.http.get(`${this.urlChar}${this.charId}${this.apiKey}`)); Observables.push(this.http.get(`${this.urlChar}${this.charId}/comics${this.apiKey}`)); } if (this.comicsId) { Observables.push(this.http.get(`${this.urlCom}${this.comicsId}${this.apiKey}`)); Observables.push(this.http.get(`${this.urlCom}${this.comicsId}/creators${this.apiKey}`)); } console.log([Observable, Observable]); return Observable.forkJoin(Observables); } } 

// my test

 import { async, ComponentFixture, TestBed, getTestBed, inject } from '@angular/core/testing'; import { MockBackend, MockConnection } from '@angular/http/testing'; import { DataService } from './data.service'; import { BaseRequestOptions, Http, XHRBackend, HttpModule, Response, ResponseOptions, RequestMethod } from '@angular/http'; import { Observable } from 'rxjs/Observable'; describe('DataService', () => { let mockBackend: MockBackend; beforeEach(async(() => { TestBed.configureTestingModule({ providers: [ DataService, MockBackend, BaseRequestOptions, { provide: Http, deps: [MockBackend, BaseRequestOptions], useFactory: (backend: XHRBackend, defaultOptions: BaseRequestOptions) => { return new Http(backend, defaultOptions); } } ], imports: [ HttpModule ] }); mockBackend = getTestBed().get(MockBackend); })); it('should get ObservableArr', (done) => { let dataService: DataService; getTestBed().compileComponents().then(() => { mockBackend.connections.subscribe( (connection: MockConnection) => { connection.mockRespond(new Response( new ResponseOptions({ body: [Observable, Observable] } ))); }); dataService = getTestBed().get(DataService); expect(DataService).toBeDefined(); dataService.getChar().subscribe((obsArr: Observable<any>[]) => { expect(obsArr.length).toBeDefined(); expect(obsArr.length).toEqual(2); expect(obsArr.length).not.toBe(1); done(); }); }); }); it('should check the service', inject([DataService], (service: DataService) => { expect(service).toBeTruthy(); })); it('should get ObservableArray async', async(inject([DataService], (dataService: DataService) => { mockBackend.connections.subscribe( (connection: MockConnection) => { connection.mockRespond(new Response( new ResponseOptions({ body: [Observable, Observable] } ))); }); dataService.getChar().subscribe( (response) => { expect(response.length).toBe(2); expect(response[0]).toBe(Observable); <<<<<<<<<<<<<< Fails expect(response[1]).toBe(Observable); <<<<<<<<<<<<<< Fails expect(response).toEqual([Observable, Observable]); <<<<<< Fails }); }))); }); 
+8
angular angular-services jasmine angular-test
source share
1 answer

First of all, as @Aviad P. pointed out, the forkJoin method does not return an array of observable observables ... it returns an array of the result of each observable in forkJoin and the result of these observables is not an instance of Observables.

In addition, you are not mocking the getChart () method, while you are mocking the layout backend for every HTTP call , but not for the getChar () method. The array must be length === 2, because not this.chartId and this.comicsId are present ...

So, I would say that the returned structure is something like this, so response [0] is an array:

 response = [[Observable, Observable], [Observable, Observable]] 

It is said that this expectation will never be true, because no array will be equal to the newly created array:

 expect(response).toEqual([Observable, Observable]) 

Changing everything that should solve your problems. In addition, if your Observables returns and an Observable instance, your code: "body: [Observable, Observable]" does not return Observables instances, it returns the Observable definition function, this will not be the correct layout, although the test will pass.

This will be a test case that fails for:

 const mockResponse = {isMockResponse: true}; it('should get ObservableArray async', async(inject([DataService], (dataService: DataService) => { mockBackend.connections.subscribe( (connection: MockConnection) => { connection.mockRespond(new Response( new ResponseOptions({ body: {...mockResponse} } ))); }); dataService.getChar().subscribe( (response) => { expect(response.length).toBe(2); expect(response[0].isMockResponse).toBe(true); <<< Is this expect really necessary? expect(response[1].isMockResponse).toBe(true); <<< Is this expect really necessary? }); }))); 

Said that, just expect to check your use case:

 expect(response.length).toBe(2); 

Others are not needed ... so you are not checking the data you are mocking, you want to test the number of calls that were made due to the value of this variables. chartId and this.comicsIs.

Hope this helps.

+1
source

All Articles