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?
interval
uses the async scheduler by default. You need to pass the TestScheduler to it, meaning you need to extend your typewriter to take an (optional) scheduler argument which it forwards tofrom
andinterval
. Forfrom
it's not needed to make it work (I believe), but since you need to add it anyway, might as well do it right :-) – Ingo Bürk