In my Angular application, I was using Observables in the following way:
getItem(id): Observable<Object> {
return this.myApi.myMethod(...); // returns an Observable
}
and I unit tested it:
it('getItem(...) should correctly do its job',
inject([MyService], (service: MyService) => {
const spy = spyOn(myApi, 'myMethod').and.returnValue(mockObservable);
const mockObservable = Observable.of('mock');
expect(service.getItem(123)).toEqual(mockObservable);
expect(spy).toHaveBeenCalledWith(...);
})
);
and it worked perfectly fine.
However if I try to add a default error-handling logic to my getItem()
method using catch
:
getItem(id): Observable<Object> {
return this.myApi.myMethod(...).catch(e => {
/* display a notification error ... */
return Observable.throw(e);
});
}
it still works fine but now the test are failing, saying:
Expected object to be a kind of ScalarObservable, but was Observable({ _isScalar: false, source: ScalarObservable({ _isScalar: true, value: 'mock', scheduler: null }), operator: CatchOperator({ selector: Function, caught: }) }).
what does it mean? why does it happen? how can I solve this issue?
thanks to @Pace's input:
expect(service.getItem(123)).toEqual(mockObservable)
fails because they are not the same object. The service method is returnning a new observable that wraps mockObservable and so the check fails. Your test would be better off subscribing to the observable returned from your service call and ensuring it returns'mock'
I found the solution:
it('getItem(...) should correctly do its job',
inject([MyService], (service: MyService) => {
const spy = spyOn(myApi, 'myMethod').and.returnValue(mockObservable);
const mockData = 'mock'; // can be anything
const mockObservable = Observable.of(mockData);
service.getItems().subscribe((data) => {
expect(data).toEqual(mockData);
});
expect(spy).toHaveBeenCalledWith(...);
})
);