pun*_*ira 4 testing reactjs jestjs redux-saga react-redux
我有这个传奇效果,它调用 API 并在成功时分派一个操作:
export function* getThemEffect() {
try {
yield put(requestActoin());
const data: AxiosResponse<ServerResponseSchema> = yield call(getStuff);
yield put(successAction(data.data.data));
} catch (err: any) {
yield put(failureAction(err?.response?.data || null));
}
}
Run Code Online (Sandbox Code Playgroud)
这是辅助函数:
export function getStuff() {
const config: AxiosRequestConfig = {
method: "GET",
url: "https://somewhere.com/api/get"
};
return axios(config);
}
Run Code Online (Sandbox Code Playgroud)
这个传奇的测试服看起来像这样:
import * as api from "../api";
const getStuffSpy = jest.spyOn(api, "getStuff");
describe("search saga", () => {
let gen: Generator, response: any, getStuffMock: jest.Mock;
beforeEach(() => {
getStuffSpy.mockClear();
gen = getThemEffect();
getStuffMock = jest.fn();
getStuffSpy.mockImplementation(getStuffMock);
});
describe("server success response", () => {
beforeEach(() => {
response = { data: { data: ["1", "2", "3"] } };
});
it("should create correct success flow", () => {
expect(gen.next()).toEqual({
value: put(requestAction()),
done: false
});
expect(gen.next()).toEqual({
value: call(api.getStuff),
done: false
});
expect(getStuffMock).toHaveBeenCalled(); // <=== this fails
expect(gen.next(response)).toEqual({
value: put(successAction(["1", "2", "3"])),
done: false
});
expect(gen.next()).toEqual({
value: undefined,
done: true
});
});
});
}
Run Code Online (Sandbox Code Playgroud)
getStuffMock然而,期望函数被调用的测试失败了。我怎样才能解决这个问题?我正在使用 jest 和测试库
call(fn, ...args)只是一个返回普通效果对象的函数。它不会fn立即执行调用。当逐步测试 saga 生成器函数时,您手动执行生成器并提供yieldby.next ()方法的值,该getStuff函数将不会执行。
只是call(getStuff)返回一个Effect对象,如下所示:
{\n CALL: {\n fn: getStuff,\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n如果你想执行模拟getStuff函数,你需要以这种方式测试 saga -测试完整的 Saga。
runSaga将获取Effect对象并执行它所拥有的函数。
测试示例:
\nsaga.ts:
import { call, put } from \'redux-saga/effects\';\nimport { getStuff } from \'./api\';\n\nexport const requestAction = () => ({ type: \'REQUEST\' });\nexport const successAction = (data) => ({ type: \'SUCCESS\', payload: data });\nexport const failureAction = (error) => ({ type: \'FAILURE\', payload: error, error: true });\n\nexport function* getThemEffect() {\n try {\n yield put(requestAction());\n const data = yield call(getStuff);\n yield put(successAction(data.data.data));\n } catch (err: any) {\n yield put(failureAction(err?.response?.data || null));\n }\n}\nRun Code Online (Sandbox Code Playgroud)\napi.ts:
import axios, { AxiosRequestConfig } from \'axios\';\n\nexport function getStuff() {\n const config: AxiosRequestConfig = {\n method: \'GET\',\n url: \'https://somewhere.com/api/get\',\n };\n return axios(config);\n}\nRun Code Online (Sandbox Code Playgroud)\nsaga.test.ts:
import { runSaga } from \'@redux-saga/core\';\nimport { call, put } from \'@redux-saga/core/effects\';\nimport { mocked } from \'ts-jest/utils\';\nimport { getStuff } from \'./api\';\nimport { getThemEffect, requestAction, successAction } from \'./saga\';\n\njest.mock(\'./api\');\n\nconst getStuffMock = mocked(getStuff);\n\ndescribe(\'search saga\', () => {\n it(\'should create correct success flow\', () => {\n const gen = getThemEffect();\n const response = { data: { data: [\'1\', \'2\', \'3\'] } };\n expect(gen.next()).toEqual({\n value: put(requestAction()),\n done: false,\n });\n expect(gen.next()).toEqual({\n value: call(getStuff),\n done: false,\n });\n\n expect(gen.next(response)).toEqual({\n value: put(successAction([\'1\', \'2\', \'3\'])),\n done: false,\n });\n expect(gen.next()).toEqual({\n value: undefined,\n done: true,\n });\n });\n\n it(\'should pass\', async () => {\n const response = { data: { data: [\'1\', \'2\', \'3\'] } };\n const dispatched: any[] = [];\n getStuffMock.mockResolvedValueOnce(response as any);\n await runSaga(\n {\n dispatch: (action) => dispatched.push(action),\n getState: () => ({}),\n },\n getThemEffect,\n ).toPromise();\n expect(dispatched).toEqual([{ type: \'REQUEST\' }, { type: \'SUCCESS\', payload: [\'1\', \'2\', \'3\'] }]);\n expect(getStuffMock).toHaveBeenCalled();\n });\n});\nRun Code Online (Sandbox Code Playgroud)\n测试结果:
\n PASS redux-saga-examples packages/redux-saga-examples/src/stackoverflow/69371886/saga.test.ts\n search saga\n \xe2\x9c\x93 should create correct success flow (4 ms)\n \xe2\x9c\x93 should pass (3 ms)\n\n----------|---------|----------|---------|---------|-------------------\nFile | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s \n----------|---------|----------|---------|---------|-------------------\nAll files | 80.95 | 0 | 60 | 78.57 | \n api.ts | 50 | 100 | 0 | 50 | 4-8 \n saga.ts | 88.24 | 0 | 75 | 90 | 14 \n----------|---------|----------|---------|---------|-------------------\nTest Suites: 1 passed, 1 total\nTests: 2 passed, 2 total\nSnapshots: 0 total\nTime: 4.662 s\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
2940 次 |
| 最近记录: |