I have a saga of the form:
export function* apiRequest(apiBaseUrl, action) {
const axiosInst = getAxiosInst(apiBaseUrl);
try {
if (!action.serviceName) {
throw new Error("No service name provided");
}
const response = yield call( axiosInst.get, `/${action.serviceName}/foo-api` );
const data = response.data;
let resultAction;
switch (response.status) {
case 404:
resultAction = INVALID_ENTITY_REQUESTED;
break;
case 200:
...
default:
throw new Error("Invalid response from server.");
}
yield put({ type: resultAction, data });
} catch (err) {
yield put({
type: ERROR,
error: err.message || "There was an unknown error."
});
}
}
export function* watchApiRequest(apiBaseUrl) {
const boundApiRequest = apiRequest.bind(null, apiBaseUrl);
yield takeEvery(API_CALL, boundApiRequest);
}
And a test like the following:
import { apiRequest } from "../services/apiRequest.js";
import MockAdapter from "axios-mock-adapter";
import { default as axios } from "axios";
import { put } from "redux-saga/effects";
import {
API_CALL,
API_SUCCESS
} from "../common/actions.js";
describe("Saga that will run on every api call event", () => {
const mock = new MockAdapter(axios);
afterEach(() => {
mock.reset();
});
it("should dispatch the correct event when an API request succeeds", () => {
mock.onGet().reply(200, { foo: "bar" });
const generator = apiRequest("", {
type: API_CALL,
serviceName: "test"
});
generator.next();
expect(generator.next().value).toMatchObject(
put({
type: API_SUCCESS,
data: { foo: "bar" }
})
);
});
});
This doesn't work. My test fails with a result like the following:
Expected value to match object:
{"@@redux-saga/IO": true, "PUT": {"action": {"type": "API_SUCCESS"}, "channel": null}}
Received:
{"@@redux-saga/IO": true, "PUT": {"action": {"error": "Cannot read property 'data' of undefined", "type": "ERROR"}, "channel": null}}
The code appears to work fine in practical usage, but when I try to test it in this way, it seems that the promise from the async call to the API via Axios doesn't resolve. I've searched around for some guidance on testing API calls in Axios like this, and seen some suggestions that instead of mocking the API response with Axios mock adapter, I should feed the generator function the response by calling generator.next({status: 200, data: { foo: "bar" })
before the expect(...)
clause, but this doesn't seem to work either.
I find the redux-saga docs on testing a little opaque, what am I doing wrong?