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); } }
0 comments:
Post a Comment