Reputation: 191729
I have a function that takes an array and returns an Observable (essentially emits each value from the given array after each delay):
export const typewriter = <T>(str: T[], delay = 20) =>
zip(interval(delay), from(str)).pipe(map(([, str]) => str));
I want to write unit tests for this, and I'm trying to use rxjs-marbles and follow the writing marble tests instructions from RxJS.
All of the examples seem to require a hot source observable and a cold observable for you to compare expected values. In this case I have a function that returns a cold observable. I've tried writing it like this:
const expected = m.hot('-^-a-b-(c|)');
const source = typewriter(['a', 'b', 'c']);
m.expect(source).toBeObservable(expected);
However I always get Expected <blank> to equal ...
, i.e. the source is blank. I think that this is because the source Observable is not hot, but even if I do
source.subscribe()
before the assertion I get the same error. Using m.cold
for the test observable doesn't matter.
How can I test a function that returns an observable using RxJS marbles?
Upvotes: 2
Views: 1969
Reputation: 58400
Your typewriter
function uses the interval
observable creator, but passes only the delay
. That means it will be using the creator's default scheduler.
To be used with marble tests, it needs to use the TestScheduler
- available via m.scheduler
.
Passing a test scheduler to a deeply-nested observable can be a pain. rxjs-marbles
includes a bind
method - see the docs - to make this a little easier:
m.bind();
const expected = m.hot('-^-a-b-(c|)');
const source = typewriter(['a', 'b', 'c']);
m.expect(source).toBeObservable(expected);
Calling bind monkey patches all of the schedulers to forward calls to the test's TestScheduler
.
Upvotes: 6