Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test timer-based RxJS observables in Jest

I'm moderately new to RxJS and very new to unit testing with Jest and I've run into a pretty confusing problem when trying to test some mocked-up RxJS observables.

In order to mimic a data stream, I created an Observable in a test spec.js file like this:

var Rx = require("rx");

var source = Rx.Observable.interval(500).take(10);

source.subscribe(
    function(x){ console.log(x) },
    function(e){ console.log(e) },
    function(){ console.log('completed') }
  );

Although this logs correctly when just ran as a node script, it doesn't log anything when ran through npm test. The Observable.delay and setTimeout functions don't appear to work as well.

like image 530
jdpigeon Avatar asked Oct 11 '25 09:10

jdpigeon


1 Answers

Here's what worked for me:

var Rx = require("rx");

describe("Interval Test", () => {
  const source = Rx.Observable.interval(100);
  let count = 0;
  source.subscribe(
  x => count++,
  e => console.log("error: ", e),
  () => console.log("complete"));

  it("run for 1 second", done => {
    setTimeout(() => {
      console.log('one second passed');
      expect(count).toBe(10);
      done();
    }, 1010)
  });
});

It seems like I needed to put a timeOut in my it test function in order for this async observable to be able to execute. Also really important was the done() call in order to prevent the time from running indefinitely.

Note: Alternately, if you want to use Jest's fake time to control timing manually, that seems to work as well. I find that I did not need to use the VirtualTimeScheduler.

jest.useFakeTimers();    
var Rx = require("rx");

var source = Rx.Observable.interval(500).take(10);

source.subscribe(
    function(x){ console.log(x) },
    function(e){ console.log(e) },
    function(){ console.log('completed') }
  );
jest.runAllTimers();
like image 175
jdpigeon Avatar answered Oct 13 '25 23:10

jdpigeon