cartant / rxjs-marbles

An RxJS marble testing library for any test framework

Home Page:https://cartant.github.io/rxjs-marbles/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to actually deal with promises?

Maximaximum opened this issue · comments

This is probably a duplicate of #11, but the original issue never contained a valid example of a workaround for the issue with Promises.

And it would be really helpful if the library supported Promises out of the box.

Because right now I'm in a situation where after a code refactoring I cannot continue using rxjs-marbles in testing my Angular ngrx effect, because it consumes a service that returns a promise.

Any help appreciated.

Thanks

This library was written before RxJS had an official, public testing API. Now that it does, this library is little more than a thin wrapper around TestScheduler#run. Any support for promises would need to be added to the TestScheduler in RxJS. However, I have reservations about mixing the virtual times of marbles with the definitely not-virtual-times of promises.

OK, I see your point, but how would you suggest to handle promises then? Because without a solution to this issue I'll have to go back to asynchronous testing of observables, which I wouldn't want to do.

There's no way around the asynchrony that's inherent in promises. Native promises cannot be monkey patched.

I would use the observe helper that's in this package. Also, IIRC, Ben talked a little about testing in this online meetup that he did a short while ago: https://www.youtube.com/watch?v=_2hvpWLyd0o

@cartant thanks a lot for your reply!

However, as far as I could find out from this example https://github.com/cartant/rxjs-marbles/blob/master/examples/jasmine/observe-spec.ts the observe() helper does not help to use the rxjs-marbles-style assertions like

m.expect(effects.openSequence).toBeObservable(
  m.cold('(1234)', expectedActions)
);

And you'll have to revert to using the plain old async-style assertions. What's the benefit of using the observe helper altogether then?

It avoids some boilerplate. That's all.

I see. Thank you!

I've watched the video you shared and I think the bottom line is, as Ben suggests: "Only use marble tests for testing custom rxjs operators, nothing more".

I tried to use marbles to test an ngrx effect (as suggested by this article https://christianlydemann.com/the-complete-guide-to-ngrx-testing/), but obviously this is not a good use case for marble tests.

It's a pity though, that there's no way to work around the Promise issue. It would be extremely convenient to use marbles for testing things like ngrx effects. Ngrx effects, similarly to operators, mostly have to do with combining different data streams, but they are too specific to be able to extract some generic functionality into custom rxjs operators.

I'll just leave a link to the rxjs Known issues here, so that anyone scratching their head around these issues can easily find it: https://rxjs.dev/guide/testing/marble-testing#known-issues

@cartant One more question please.

Is there a way to use both observe() (to get rid of the done callback) and marbles() (to create hot/cold observables for tests)? I couldn't find such an example

Nope. You cannot use hot and cold without the TestScheduler and virtual time. Use subjects for hot observables and of for cold, etc.