unit testing - How can I avoid passing the scheduler through my business logic, when writing tests for RXJS observables? -


i finding way make tests pass explicitly pass scheduler functions. illustration, consider function:

function dostuff( stream ){     return stream.delay(100)         .filter( x => x % 2 === 0 )         .map( x => x * 2 )         .flatmaplatest( x=> rx.observable.range( x, x+100) ) 

and test:

it('example test', () => {     let scheduler = new rx.testscheduler()     let xs = scheduler.createhotobservable(         onnext(210, 1),         onnext(220, 2),         onnext(230, 3)     )      let res = scheduler.startscheduler(         () => dostuff( xs, scheduler ),         {created:0, subscribed:200, disposed:1000})      expect( res.messages ).toequal( [         onnext(321, 4),         onnext(322, 5),         onnext(323, 6)     ] ) }) 

which gives error:

    expected [  ] equal [ ({ time: 321, value: onnextnotification({ value: 4, kind: 'n' }), comparer: function }), ({ time: 322, value: onnextnotification({ value: 5, kind: 'n' }), comparer: function }), ({ time: 323, value: onnextnotification({ value: 6, kind: 'n' }), comparer: function }) ]. 

this suggests delay happening in real time instead of simulated time of testscheduler.

if pass scheduler every operator, can make work:

function dostuff( stream, scheduler ){    return stream.delay( 100, scheduler )       .filter( x => x % 2 === 0 )       .map( x => x * 2 )       .flatmaplatest( x => rx.observable.range(x, 3, scheduler ) ) } 

but feels me should able set scheduler once , not have have real production code have thread through. expecting that, given original stream created testscheduler , run via same scheduler, automatically wired up.

the rx guidelines suggest consider passing specific scheduler concurrency introducing operators. single-threaded javascript, there no concurrency, time-based operators delay() have similar concern.

this isn't bad first thought, majority of operators not have scheduler argument, , subset of time-based. , highlights why explicitly pass scheduler. in example above, passed through scheduler every operator supported it, results weren't expected - tweaked "expected" result make work:

expect( res.messages ).toequal( [     onnext(321, 4),     onnext(322, 5),     onnext(323, 6) ] ) 

but really, expecting of timings 320.

for delay(), need inherit scheduler test, range() want default scheduler instead, because schedule events immediately.

my final example code snippet this:

function dostuff( stream, scheduler ){     return stream.delay( 100, scheduler )         .filter( x => x % 2 === 0 )         .map( x => x * 2 )         .flatmaplatest( x => rx.observable.range(x, 3)) } 

when creating tests, always want using testscheduler time-based operators. other operators want use defaultscheduler regardless of if test running.


Comments

Popular posts from this blog

php - Invalid Cofiguration - yii\base\InvalidConfigException - Yii2 -

How to show in django cms breadcrumbs full path? -

ruby on rails - npm error: tunneling socket could not be established, cause=connect ETIMEDOUT -