Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Observable.fromPromise empty during unit testing

loadAdList$ is an Observable that taps into the actions$ stream:

loadAdList$: Observable<Action> = this.actions$
    .ofType<adActions.Load>(adActions.LOAD)
    .switchMap((action) => {
      return Observable.fromPromise(store.findAll('ad', action.payload)
        .then((ads) => {
          return new adActions.LoadSuccess(ads);
        })
        .catch((err) => {
          return new adActions.LoadFail(err);
        }));
    });

It works in the browser, there is no problem with it. However, I want to unit test it as well:

actions$ = hot('-a', { a: loadAction });
const storeResponse = Promise.resolve(mockAds);
const expected$ = cold('-c', { c: loadSuccessAction });

spyOn(store, 'findAll').and.returnValue(storeResponse);

expect(effects.loadAdList$).toBeObservable(expected$);

The test fails with the following:

Expected 

to deep equal 
    {"frame":10,"notification":{"kind":"N","value":{"payload":"[
    ...

I believe the issue has something to do with the store.findAll method returning a promise. This is based on the results of the following test:

.switchMap((action) => {
  // This test will pass
  return Observable.from([new adActions.LoadSuccess(mockAds)]);

  // This test will fail
  return Observable.fromPromise(Promise.resolve(new adActions.LoadSuccess(mockAds)));

});
like image 918
Moo Avatar asked Sep 08 '17 00:09

Moo


1 Answers

It is bit unfortunate but there wasn't great way to make promise resolves synchronously under context of TestScheduler in Rx v5. For those reason, if Observable source started off from promise it won't work with marble testings and you have to create assertion differently by subscribing.

Check https://github.com/ReactiveX/rxjs/issues/701 / https://github.com/ReactiveX/rxjs/pull/745 if you'd like to have detail why it wasn't successful.

like image 128
OJ Kwon Avatar answered Nov 15 '22 09:11

OJ Kwon