Reputation: 3340
I'm using ngrx/effects with marbles testing. I have a service that uses promises. I want my effect to call the service and handle both successful and error states. I have code like this
Effect:
.mergeMap(() =>
this.service.getThings()
.map((things) => new SetThingsAction(things))
.catch((error) =>
of(new HandleAPIErrorAction(error))
)
)
.catch((error) =>
of(new HandleAPIErrorAction(error))
);
Service:
public geThings() {
return Observable.fromPromise(this.promiseBasedThing.getTheThings());
}
Then a test:
actions = hot("a", { a: new GetThingsAction() });
const response = cold("-#", {});
service.getThings.and.returnValue( response );
const expected = cold("-b", { b: new HandleAPIErrorAction("error") });
expect(effects.getThings$).toBeObservable(expected);
This actually all works. However the double catch in the effect seems clearly bad and probably suggests I don't understand how Observables work. In the real world only the later catch is effective. In a test the first is effective.
Based on this it seems like Promises don't work with marbles tests. This SO question gives an idea on error handling but it seems impossible to test because it has a Promise.
How can I use ngrx/effects with error handling, promises, and testing.
Upvotes: 2
Views: 968
Reputation: 3340
Can answer my own after further research.
https://jsfiddle.net/btroncone/upy6nr6n/
Basically I needed to do the catch in the getThings instead of in the effect.
getThings() {
return Observable.fromPromise(this.promiseBasedThing.getTheThings())
.catch((error) => Observable.of(error));
}
Also learned that it's much easier to solve these problems with a simple rsjx example instead of trying to solve it while using ngrx/effects too. This still has two catch statements, but the test mocking now matches how it works in reality.
Upvotes: 2