Picci
Picci

Reputation: 17762

Jasmine spyOn with Observables - using arrow functions vs passing the function to an RxJs operator

I have a function, actually a method in a Typescript class called HouseService, that looks like this

myHouse() {
    return this.bricks$
    .pipe(
      map(bricks => this.buildHouse(bricks)),
    );
}

this method listen to an Observable, this.brick$, and as soon as some bricks are notified builds a house using the method `this.buildHouse(bricks: Array).

Then I write a test that checks that this.buildHouse method is only called once. The test looks like this and works perfectly

  it('"buildHouse()" method is called only once for one event of "bricks$"', () => {
    spyOn(houseService, 'buildHouse').and.callThrough();
    houseService.bricks$.next(newBricks);
    expect(houseService.buildHouse).toHaveBeenCalledTimes(1);
  });

So far everything works fine.

Now the problem. I change the implementation of the myHouse method, getting rid of the fat arrow function and substituting it with the pure method reference, as follows

myHouse() {
        return this.bricks$
        .pipe(
          map(this.buildHouse),
        );
}

The runtime continues to work perfectly, but the test does not work anymore since it reports that buildHouse has been called 0 times. Can anybody explain why?

Upvotes: 0

Views: 723

Answers (1)

Martin Nuc
Martin Nuc

Reputation: 5764

Because your myHouse function is executed before you mock that function. Therefore the original (not mocked) function is passed to map.

With arrow function it's executed each time the map calls it's callback - at that time the buildHouse is already mocked.

Upvotes: 2

Related Questions