react-redux - 如何在 redux-saga 中测试异步 axios 请求?
问题描述
我有一个形式的传奇:
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);
}
以及如下测试:
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" }
})
);
});
});
这行不通。我的测试失败,结果如下:
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}}
该代码在实际使用中似乎运行良好,但是当我尝试以这种方式对其进行测试时,似乎通过 Axios 对 API 的异步调用的承诺无法解决。我已经搜索了一些关于在 Axios 中测试 API 调用的指导,并且看到了一些建议,而不是使用 Axios 模拟适配器模拟 API 响应,我应该通过generator.next({status: 200, data: { foo: "bar" })
在子句之前调用来为生成器函数提供响应expect(...)
,但这并没有似乎也不起作用。
我发现关于测试的 redux-saga 文档有点不透明,我做错了什么?
解决方案
我想出了答案。这是关于生成器函数的性质。
generator.next()
将生成器推进到下一yield
条指令;出于这样的测试目的,实际上不需要模拟对 API 请求的响应,您可以通过将所需的值传递给生成器的next()
方法来将响应注入生成器。
所以,在我上面的测试代码中,有两个调用next()
. 第一次调用next()
将导致 saga 发出其 API 请求。第二个将前进到下一个产量,或者在 catch 块中分派操作put()
或分派错误。诀窍是应在第二次调用中提供所需的模拟 API 响应next()
推荐阅读
- reactjs - 如何在本机反应中使用水平体重计
- git - Git认为还原后没有什么可拉的
- vba - 将文本框多行传递给 xml
- azure - 多个与指定模式匹配的包:D:\a\r1\a\**\*.zip。请限制搜索模式
- python - 如何用 Pandas Dataframe 中的每一列绘制每一列?
- javascript - 我想将输入字段中写入的文本保存在 localStorage
- http - prometheus 用于提取 SPARQL 端点指标
- reactjs - React 的 useSelector 和对象数组
- bash - “libiomp5.so 无法打开共享对象文件”如何在 Windows 10 中解决问题?
- chatbot - 如何在 rasa 中发出用户输入错误消息?