Search code examples
typescriptjasminerxjsangular-observableangular-test

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


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?


Solution

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