Here’s a way to test a redux-observable epic that performs an ajax call.
This simplified TypeScript
example has three actions: USER_LOAD_REQUEST
is the result of a request to load a user,
USER_LOAD_RESULT
indicates a successful response, and USER_LOAD_ERROR
holds an
ajax error.
|
|
Testing is straightforward with ReduxObservable’s
dependency injection
parameter. In this case, I’m injecting the ajax.getJSON
property into the epic.
Mocking the AJAX call involves either wrapping a plain JS object or a plain JS Error
in an
Observable
.
import { ActionsObservable } from "redux-observable";
import "rxjs/Rx";
import { Observable } from "rxjs/Observable";
import * as example from "./exampleEpic";
const successResult: example.IUserResult = {
id: "123",
name: "Test User"
};
describe("loadUserEpic", () => {
// done: see https://facebook.github.io/jest/docs/asynchronous.html
it("dispatches a result action when the user is loaded", (done) => {
const dependencies = {
getJSON: url => Observable.of(successResult)
};
const action$ = ActionsObservable.of(example.loadUser(successResult.id));
const expectedOutputActions = example.loadUserResult(successResult);
const result = example.loadUserEpic(action$, null, dependencies).subscribe(actionReceived => {
expect((actionReceived as any).type).toBe(expectedOutputActions.type);
done();
});
});
it("dispatches an error action when ajax fails", (done) => {
const errorMessage = "Failed Ajax Call";
const dependencies = {
getJSON: url => Observable.throw(new Error(errorMessage))
};
const action$ = ActionsObservable.of(example.loadUser(successResult.id));
const expectedOutputActions = example.loadFailure(`An error occurred: ${errorMessage}`);
const result = example.loadUserEpic(action$, null, dependencies).subscribe(actionReceived => {
expect((actionReceived as any).type).toBe(expectedOutputActions.type);
expect((actionReceived as any).message).toBe(
expectedOutputActions.message);
done();
});
});
});
Note the done
parameter—this is a way of
signaling to jest that an async call has completed.