Expected object to be a kind of ScalarObservable, but was Observable

Francesco Borzi picture Francesco Borzi · Nov 24, 2017 · Viewed 7.1k times · Source

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?

Answer

Francesco Borzi picture Francesco Borzi · Nov 26, 2017

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(...);
  })
);