How to do unit test for Http get MockBackend in Angular2?

How to do unit test for Http-receiving MockBackend in Angular2?

I am having trouble testing my http unit test. Every time I look at MockBackend , it seems confusing, a lot of code and some imports never work.

I just need a very simple http get unit test

I use: typescript, angular2, jasmine and karma runner.

My actual code is working fine.

Here is my code that I am testing:

  import {Injectable} from 'angular2/angular2'; import {HTTP_PROVIDERS, Http, Headers} from 'angular2/http'; @Injectable() export class FirebaseService{ headers: Headers; //Test issue seems to be here when I inject Http instance. constructor(public http?: Http) { this.headers = new Headers(); this.headers.append('Content-Type', 'application/json'); } //This is the method I'm testing. public getSpotifyTracks = ():Promise<Object> =>{ return this.http .get('https://api.spotify.com/v1/tracks/0eGsygTp906u18L0Oimnem', {headers:this.headers}) .map((response) => { return response.json() }).toPromise(); } } 

Here is my unit test for this code:

 import {it, iit, describe, expect, inject, injectAsync, beforeEachProviders, fakeAsync, tick} from 'angular2/testing'; import {HTTP_PROVIDERS, Http, Headers} from 'angular2/http'; import {FirebaseService} from '../app/firebase-service'; describe('Firebase Service Calls', () => { beforeEachProviders(()=> [Http, FirebaseService]); //Issue seems to be here???? it('get all tracks from spotify', injectAsync([FirebaseService],(service) => { return service.getSpotifyTracks().then((response) => { expect(response.length).not.toBe(null); }); }), 3000); }); 
+6
source share
4 answers

First import all the modules:

 import {it,describe,expect,inject,injectAsync,beforeEachProviders} from 'angular2/testing'; import {provide, Injector} from 'angular2/core'; import {MockBackend} from 'angular2/http/testing'; import {YourServiceToBeTested} from 'path/to/YourServiceToBeTested'; 

Then you need to declare Mocked HttpBackend:

 describe('Service with Http injected', () => { beforeEachProviders(() => { [ MockBackend, BaseRequestOptions, provide( Http, { useFactory: (backend, defaultOptions) => { return new Http(backend, defaultOptions); }, deps: [MockBackend, BaseRequestOptions] }), YourServiceToBeTested ] }); 

Finally, on each test, you need to enter a layout and set the mock value (i.e. fake data returned by your service for this particular test)

 it('should respect your expectation', inject( [YourServiceToBeTested, MockBackend], (yourServiceToBeTested, mockBackend) => { let response = 'Expected Response from HTTP service usually JSON format'; let responseOptions = new ResponseOptions({body: response}); mock.connections.subscribe( c => c.mockRespond(new Response(responseOptions))); var res = yourServiceToBeTested.ServiceMethodToBeTest(serviceParams); expect(res).toEqual('your own expectation'); })); 
+4
source

While @ f-del s answer gets the same result, it is easier and better to use Angulars DI.

 describe('Firebase Service Calls', () => { beforeEachProviders(()=> [ HTTP_PROVIDERS, MockBackend, provide(XHRBackend, {useExisting: MockBackend})]); 

That way, when Http requested and an instance is provided that uses MockBackend .

+2
source

In Angular 2.2.1, ensure no longer exists in the kernel, so we must do:

 { provide : Http, deps : [ MockBackend, BaseRequestOptions ], useFactory : ( backend : MockBackend, defaultOptions : BaseRequestOptions ) => { return new Http( backend, defaultOptions ); } } 
+2
source

To put together @Milad's answer, I found an excellent http-taunting tutorial for Angular 2/4 tests.

searchService.service.ts

 import {Injectable} from '@angular/core'; import {Jsonp} from '@angular/http'; import 'rxjs/add/operator/toPromise'; class SearchItem { constructor(public name: string, public artist: string, public thumbnail: string, public artistId: string) { } } @Injectable() export class SearchService { apiRoot: string = 'https://itunes.apple.com/search'; results: SearchItem[]; constructor(private jsonp: Jsonp) { this.results = []; } search(term: string) { return new Promise((resolve, reject) => { this.results = []; let apiURL = `${this.apiRoot}?term=${term}&media=music&limit=20&callback=JSONP_CALLBACK`; this.jsonp.request(apiURL) .toPromise() .then( res => { // Success this.results = res.json().results.map(item => { console.log(item); return new SearchItem( item.trackName, item.artistName, item.artworkUrl60, item.artistId ); }); resolve(this.results); }, msg => { // Error reject(msg); } ); }); } } 

searchService.service.spec.ts

 describe('Service: Search', () => { let service: SearchService; let backend: MockBackend; beforeEach(() => { TestBed.configureTestingModule({ imports: [JsonpModule], providers: [ SearchService, MockBackend, BaseRequestOptions, { provide: Jsonp, useFactory: (backend, options) => new Jsonp(backend, options), deps: [MockBackend, BaseRequestOptions] } ] }); backend = TestBed.get(MockBackend); service = TestBed.get(SearchService); }); }); it('search should return SearchItems', fakeAsync(() => { let response = { "resultCount": 1, "results": [ { "artistId": 78500, "artistName": "U2", "trackName": "Beautiful Day", "artworkUrl60": "image.jpg", }] }; // When the request subscribes for results on a connection, return a fake response backend.connections.subscribe(connection => { connection.mockRespond(new Response(<ResponseOptions>{ body: JSON.stringify(response) })); }); // Perform a request and make sure we get the response we expect service.search("U2"); tick(); expect(service.results.length).toBe(1); expect(service.results[0].artist).toBe("U2"); expect(service.results[0].name).toBe("Beautiful Day"); expect(service.results[0].thumbnail).toBe("image.jpg"); expect(service.results[0].artistId).toBe(78500); })); 

The code and credit are owned by Asim at CodeCraft.

0
source

All Articles