How to test observables which emit grouped events with rxjs marbles?
Asked Answered
M

2

7

According to rxjs marbles documentation the current behaviour for the sync groupings is the following:

'(ab)-(cd)': on frame 0, emits a and b then on frame 50, emits c and d

From the docs:

While it can be unintuitive at first, after all the values have synchronously emitted time will progress a number of frames equal to the number of ASCII characters in the group, including the parentheses

Ok, but how do I test an observable like this (using marbles or any other technique):

const observable$ = of(1, 2).concat(of(3, 4).delay(20));

Are there any workarounds?

There is a similar question on Stack Overflow but there is no answer on 'How to actually work around it and test this kind of observable'.

Thanks!

Mediacy answered 18/5, 2018 at 8:26 Comment(0)
M
4

For my project I migrated to rx-sanbox where sync grouping works correct and it solved my problem.

So, in rx-sandbox this is correct: '(ab)-(cd)': on frame 0, emits a and b then on frame 20, emits c and d

Mediacy answered 25/5, 2018 at 13:42 Comment(0)
H
2

I don't know what version of RxJS you're using because you're mixing prototypical and pipable operators but it looks like RxJS 5.5.

In RxJS 5.X it's a bit clumsy. You could rewrite your test like this:

import { of } from 'rxjs/observable/of';
import { TestScheduler } from 'rxjs/testing/TestScheduler';
import { assert } from 'chai';
import 'rxjs/add/operator/concat';
import 'rxjs/add/operator/delay';

const scheduler = new TestScheduler((actual, expected) => {
  console.log(actual, expected);
  return assert.deepEqual(actual, expected);
});

const observable$ = of('a', 'b').concat(of('c', 'd').delay(50, scheduler));

scheduler
  .expectObservable(observable$)
  .toBe('(ab)-(cd|)');

scheduler.flush();

See live demo (open console): https://stackblitz.com/edit/rxjs5-marble-test?file=index.ts

You know this test passes because it doesn't throw any error. Try changing any of the delays or values of next emissions and it'll throw an error.

Also have a look at this answer: How do I test a function that returns an observable using timed intervals in rxjs 5?

However, I'd strongly recommend upgrading to RxJS 6 because it makes everything much easier with cold and hot "creation" functions where you could just use const observable$ = cold('(ab)-(cd|)') to create the same sequence as you're doing with of(...).concat(...).

Testing in RxJS 6:

Hobbism answered 18/5, 2018 at 14:6 Comment(2)
Well, if you want to use marble tests you'll have to at least pass the scheduler to delay. Otherwise it's not able to work with time and marble tests are based proper on timing.Hobbism
Thank you for the detailed answer, @martin. In your answer you assumes that I can edit my original observable. But I'm trying to test some observable from the real code of my application. ` class SomeService { observable$ = of(a, b).concat(of(c, d).delay(20)); } ` I know that this observable suppose to produce the following stream: '(ab)-(cd)'. And I want to test it using marbles. My problem is that using the marble syntax i can't do it because of sync groupings syntax. In Rxjs 6 too. For my project I migrated to rx-sanbox where sync grouping works correct and it solved my problemMediacy

© 2022 - 2024 — McMap. All rights reserved.