Epics can be unit-tested just like any other function in your application - they have a very specific set of inputs (the action$ stream) and the output is always an Observable. We can subscribe to this output Observable to assert that the actions going back into the Redux are the ones we expect.
Epics can be unit tested, just like any other piece of code. At their core, they are simply functions that take in a stream of actions, operate upon that stream, and they return another stream of actions.
In this example, I've just created a fake one, where we have a fetch-user action, and then, in the middle here, we will do some call to an API, or something like that. Eventually, you'll map it into another action that has the result of that API call. That's what you can see here.
We have inputs, and we have outputs. It sounds like we have everything we need for testing, it's just that, because we're dealing with observables, we need to do a little bit more work to get at the values. Let's handle the input first.
It looks like we're going to need this actions that has an of-type method, and returns an observable for us. We could do this manually. We could simply say actions is equal to an object that has an of-type method that, when called, returns, we'll bring in observable from RxJS. This will return observable of type fetch-user, and a payload of, let's say, [inaudible 1:25] .
That's how we can mock the actions manually, but Redux-observable actually has a helper to do this for you, that is the actions-observable. If we bring in actions-observable from Redux-observable, we can say actions-observable of, then we can pass in our action.
If we log this out, you'll see that we'll get an observable. If we look back at our function, it only takes this one argument. We should be able to say that the output is equal to, fetch-user epic. We'll pass in that action stream, and then we just need to subscribe to it, and each element that comes out of this stream will be an action.
There, you can see, when we sent in fetch-user, we got fetch-user fulfilled. If we made a typo here, we wouldn't get any actions. What this allows us to do is we can aggregate everything that comes out of our epic into a single array. Now, when I log this, you can see that this is now an array of actions.
You can then start asserting on the output. You can say that, as an example, we change this to actions, now that we've called to-array.
We could start to say things like we expect actions.length to be one. In our fetch-user epic, if, for some reason, we went and did something like ignore elements on this by mistake, and left it in place, we would get an error, and then we'd know what was going on.
This is really the basics of testing with Redux-observable. You need a way of mocking the inputs, and because it returns an observable, you can always just subscribe to it, and then assert on the actions that come out the other end.