Friday, April 7, 2017

Mocking service calls that return observables in Angular 2?

Leave a Comment

I have been trying to mock some service calls that return observables in my Angular app, but i simply can't create a valid observable that will trigger calls like catch() or map() in my code. For example:

My service:

create(): Observable<any> {     return this.http     .post('/api/stuff', { id: 123 })     .catch(this.handleError)     .map(this.extractData); } 

My spec:

let authHttpMock = mock(AuthHttp); when(authHttpMock.post('/api/stuff', { id: 123 })).thenReturn(Observable.create(observer => {   observer.error(new Error('500!')); }));  const myService = new MyService(instance(authHttpMock)); myService.create({ id: 123 }).subscribe(     result => {     expect(result).toBeTruthy();     } ); 

The coverage analysis tells me that the handleError method has never been executed. On the case of a successful observable, it also doesn't go through the extractData method.

Where is that observable going to? How can i return a proper observable in order to test such calls?

3 Answers

Answers 1

There are two ways you can achieve this.

First would be, in your service method, use the following:

create(id:number):Obserable<any> {   let url:string = 'http://localhost:3000/api/stuff';   let data:any = {     id: id   };    return this.http.post(url, JSON.stringify(data))     .map((res:Response) => res.json());     .catch((error:any) => this.handleError(error)) } 

The second method would be, call use the service as follows:

create(id:number):Obserable<any> {   let url:string = 'http://localhost:3000/api/stuff';   let data:any = {     id: id   };    return this.http.post(url, JSON.stringify(data))     .map((res:Response) => res.json());   } 

And when you call the service method, use this:

this._service.create(123)   .subscribe((res:any) => {     //do whatever with success   },   (error:any) => {     this.handleError(error)   }); 

The method you are using to extract data, this.extractData(), can be called instead of res.json() inside the service, but overall it's the same result.

Hope this helps :)

Answers 2

Somewhere in your test code I believe you need to have this code: AuthHttp.post('/api/stuff', {id : 123 }).subscribe(data => {});

Answers 3

You need to create mockData first so that service can make use of it.There is 2 files below. Put your component and service name in place of COMPONENT_NAME & SERVICE_NAME respectively.

Spec File ts

describe('WalletComponent', () => {   let component: WalletManagementComponent;   let fixture: ComponentFixture<WalletManagementComponent>;    beforeEach(async(() => {     TestBed.configureTestingModule({       imports: [ReactiveFormsModule],       declarations: [COMPONENT_NAME],       schemas: [NO_ERRORS_SCHEMA],       providers: [         {provide: APP_BASE_HREF, useValue: '/'},         {provide: SERVICE_NAME, useClass: serviceMockData}             ]     }).compileComponents();   }));    beforeEach(() => {     fixture = TestBed.createComponent(COMPONENT_NAME);     component = fixture.componentInstance;     fixture.detectChanges();   });    it('Should create WalletComponent', () => {     expect(component).toBeTruthy();   });   }); 

You need to create directory called testHelper(or any name) in root directory

serviceMockData ts

import {Observable} from 'rxjs/Observable';  const result = {   data: [     {id: 0, name: 'Temp Data 1'},     {id: 1, name: 'Temp Data 2'},   ] };   export class serviceMockData {   constructor() {   }    getWalletAudits() {     return Observable.of(result).map(res => res);   }  } 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment