2

I am trying to spy on RxJS operators with Jasmine. There are different use cases in my tests where I want to be in control on what a Observable returns. To illustrate what I am trying to do I have created the example above even thought it does not make to much sense as this observable always returns the same hard coded string. Anyway it is a good example to show what I am trying to achieve:

Imagine I have the following Class.

import {Observable} from 'rxjs/Observable';
import {of} from 'rxjs/observable/of';

export class AwesomeTest {

   constructor() {
   }

   getHero(): Observable<string> {
      return of('Spiderman');
   }
}

And the following test:

import {AwesomeTest} from './awesomTest';
import {of} from 'rxjs/observable/of';
import createSpyObj = jasmine.createSpyObj;
import createSpy = jasmine.createSpy;

describe('Awesome Test', () => {

  let sut;

  beforeEach(() => {
    sut = new AwesomeTest()
  })

  fit('must be true', () => {
    // given
    const expectedHero = 'Superman'
    const asserter = {
        next: hero => expect(hero).toBe(expectedHero),
        error: () => fail()
    }
    createSpy(of).and.returnValue(of('Superman'))
    // when
    const hero$ = sut.getHero()
    // then
    hero$.subscribe(asserter)
  });
});

I try to spy on the Observable of operator and return a Observable with a value that I specified inside my test instead of the actual value it will return. How can I achieve this?

Before the new Rx Import Syntax I was able to do something like this:

spyOn(Observable.prototype,'switchMap').and.returnValue(Observable.of(message))

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Trafalgar
  • 361
  • 1
  • 4
  • 14

1 Answers1

2

In your spec file, everything as a wildcard (don't worry about tree shaking, this is just for the tests)

import * as rxjs from 'rxjs';

You can then use rxjs for your spying

spyOn(rxjs, 'switchMap').and.returnValue(rxjs.of(message))
  • 2
    When I try this approach with the `zip` function I receive this error during the execution of my test: `Error: : zip is not declared writable or has no setter Usage: spyOn(, )`. Perhaps this approach doesn't work for all operators? – risingTide Dec 03 '18 at 22:06
  • @risingTide at least in the lastest versions of things, you should use spyOnProperty... `spyOnProperty(rxjs, 'switchMap', 'get').and.returnValue...` – Tom McKearney Jan 06 '20 at 14:08
  • 1
    Now I am getting `Error: : switchMap is not declared configurable` :-( Any ideas? – Markus Kollers Apr 08 '20 at 17:18
  • I've done a lot of research on this in the past few days and spying on functions that are not part of an object instance (global functions) seems to be not supported in Jasmine for all configurations. It may be more closely related to usage of Webpack or other transpilers causing issues. At any rate there are a lot of suggested solutions out there and I have yet to find one that works in an Angular 12 environment. – jake Sep 24 '21 at 11:19