Search code examples
javascriptrxjsrxjs5rxjs-test-scheduler

The right way to test rxjs


I brought the book "rxjs in action" and just finish the testing section.

Testing rxjs codes are different then usual testing, because everything are lazy loading.

In the book, they mention two test method, either passing done(I am using QUnit and done signals async code is finish) or marble diagrams.

My question is, which method should I choose, that I have mentioned above?


Solution

  • I have been getting this question a lot from my colleagues. I finally got around to document my ways of testing RxJs on my blog. Since your question seems to be related to RxJs5 i will only quote the relevant part of my post here.

    Testing in RxJs5 the RxJs4 way

    When you migrate your codebase from RxJs4 towards 5 you will find out that a lot of things have been moved, renamed and above all that the implementation of the TestScheduler is no longer available. RxJs contributor kwonoj has created a compatibility shim to help migration towards RxJs5. You can install it using npm npm install @kwonoj/rxjs-testscheduler-compat. Not all features of the TestScheduler are implemented but the most important .startScheduler is working.

    const TestScheduler = require('@kwonoj/rxjs-testscheduler-compat').TestScheduler;
    const next = require('@kwonoj/rxjs-testscheduler-compat').next;
    const complete = require('@kwonoj/rxjs-testscheduler-compat').complete;
    
    it('works in RxJs5 with the compat package', () => {
      const scheduler = new TestScheduler(); // Note; no longer the Rx.TestScheduler
    
      const results = scheduler.startScheduler(
        () => Rx.Observable.interval(100, scheduler).take(3),
        { created: 100, subscribed: 200, unsubscribed: 1000 } // NOTE: disposed is now renamed to unsubscribed
      );
    
      collectionAssert.assertEqual(res.messages, [
        next(200 + 100, 0),
        next(200 + 200, 1),
        next(200 + 300, 2),
        complete(200 + 300)
      ]);
    });
    

    Testing in RxJs5 using the new Marble testing syntax

    The RxJs team has introduced marble testing syntax to more visually define how your operator or custom code should operate.

    var e1 = hot('----a--^--b-------c--|');
    var e2 = hot(  '---d-^--e---------f-----|');
    var expected =      '---(be)----c-f-----|';
    
    expectObservable(e1.merge(e2)).toBe(expected);
    

    At the time of writing this post they have not yet made this approach really easy to use outside of the RxJs5 library itself. There are implementations available to see how to do it yourself. You can also look around in the codebase of RxJs5 to see how to setup your testing framework to do your own marble tests. There is an open issue about documenting testing with RxJs5. I have not yet succeeded to get my testing framework setup to do marble testing in this way.