I have a data service which fetches the data from server and makes multiple requests which then return an array of observables. I want to test the data.
What i tried doing is in the mockrespone I sent array which contains two observables i dont know if thats the right way to test data.
But tests are failing especially the last three tests in the async test block
Important: I want to test that, when setting charId to falsy and comicsId to falsy, calling tthe method, subscribing to the observable it returns, after you've mocked http, you get back an array containing the two expected responses. Same with the 4 expected response if charId is truthy. Same for the 6 expected responses when comicsId is truthy
// the service which fetches the 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
});
})));
});
Using the HttpClientTestingModule and HttpTestingController provided by Angular makes mocking out results and testing http requests simple by providing many useful methods for checking http requests and providing mock responses for each request.
First of all, as @Aviad P. pointed, forkJoin method doesn't returns an Observable array of observables... it returns an array of the result of every observable in the forkJoin, and the result of that observables are not Observables instances.
Also, you are not mocking the getChart() method, with the mock backend you are mocking every http call, but not the method getChar() itself. 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 that, so response[0] is an array:
response = [[Observable, Observable], [Observable, Observable]]
Said that, this expect will never be true, because no one array would be equal to a new array created:
expect(response).toEqual([Observable, Observable])
Modifying all that should resolve your problems. Also, In case your Observables returned and Observable instance, your code: ' body: [Observable, Observable] ' is not returning Observables instances, it is returning the Observable definition function, this would be a not correct mock, although the test would pass.
This would be a test example for ones is failing:
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, The only expect that test your use case is this ones:
expect(response.length).toBe(2);
The other ones are unnecessary... so you are not testing the data you are mocking, you want to test the number of calls that has been performed due to the value of the variables this.chartId and this.comicsIs.
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With