Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I mock fromEvent function from RXJS 5.5.6?

I have to test a function that uses the fromEvent observable function. Before the upgrade to 'lettable' operators, I was just doing this:

spyOn(Observable, 'fromEvent').and.callFake(mockFromEventFunction)

But now, Rxjs have changed, and Observable.fromEvent is just a function named fromEvent, that is imported like this: (and used the same way)

import { fromEvent } from 'rxjs/observable/fromEvent';

My question is, how I can mock that function with Jasmine spy utilities without knowing it's parent context?

I advise that this doesn't work:

import * as FromEventContext from 'rxjs/observable/fromEvent';
...
spyOn(FromEventContext , 'fromEvent').and.callFake(mockFromEventFunction)

Now I have a workaround wrapping that fromEvent in one Object which I know the context. But I am wondering how I can solve this cleanly.

Thanks in advance.

like image 591
Llorenç Pujol Ferriol Avatar asked Jan 24 '18 11:01

Llorenç Pujol Ferriol


People also ask

What is FromEvent in RxJs?

FromEvent: FromEvent is a method provided by RxJs to create Observable. The best thing is that we can create Observable from DOM events directly. By DOM events, it means click event, key up events, scroll events, etc. that is a simple mouse click, we can create a stream of data, i.e. an Observable.

Which of the following will create an observable from an event using RxJs in angular?

Angular provides FromEvent method to create an observable from DOM events directly.


1 Answers

After some investigation I discovered that the fact that we can or cannot mock this single exported functions is directly dependen in how our bundler resolves the modules when testing.

So for example, you may stumble to this error or similarly:

Error: : myFunctionName is not declared writable or has no setter

Caused because the bundler just wrapped those lonely exported functions into a getter property, making them impossible to mock.

The solution that I ended using is compile modules in 'commonjs' when testing.

For example, if you are working with typescript, you would need to change change your tsconfig.spec.ts to use commonjs module:

"compilerOptions": {
     ....
      // force commonjs module output, since it let mock exported members on modules to anywhere in the application (even in the same file)
      "module": "commonjs",
  },

The resultant output of any exported member of a module in commonjs would be like: exports.myFunc = function() {}. This led use spyOn without worries since it is wrapped on the 'exports' object. One great use case of that, is that it would be mocked anywhere, including the usages in its own file!

Example:

// some-module.js
export function functionToMock() {
     return 'myFuncToMock';
}
export function functionToTest() {
     return functionToMock();
}

// testing-module.spec.js
import * as SomeModule from ./some-module
spyOn(SomeModule, 'functionToMock').and.returnValue('mockedCorrectly');
SomeModule.functionToTest().toBe('mockedCorrectly')
like image 134
Llorenç Pujol Ferriol Avatar answered Oct 20 '22 01:10

Llorenç Pujol Ferriol