Redux-Saga接口调用测试问题:dispatched数组未更新
Redux-Saga测试异常:dispatched数组未更新但控制台可输出动作
问题说明
一直用该方式测试Redux-Saga,本次测试出现异常:dispatch回调内的控制台能正常输出响应动作,但dispatched数组并未更新,导致测试断言失败。
相关代码
Saga代码
export function* releaseCommitsSaga({ release, product } ) { if (release && product) { const response = yield fetch(`${ApiEndpoint}/ReleaseCommits?${getURLQueryParams({ product, version: release })}`); const releaseCommits = yield response.json() .catch((error) => error); if (response.status === 200) { console.log(releaseCommits); yield put(getReleaseCommitsSuccess(releaseCommits)); } else { yield put(getReleaseCommitsFailure('release commits could not be fetched')); } } else { yield put({ type: INVALID_PAGE_LOAD, }); } }
测试代码
it('releaseCommitsSaga success', async () => { const response = responses.getReleaseCommitsResponse('success'); global.fetch = jest.fn(() => Promise.resolve({ status: 200, json: () => Promise.resolve(response), })); const dispatched = []; await runSaga({ dispatch: (action) => { console.log(action); dispatched.push(action); }, }, releaseCommitsSaga, getReleaseCommits(release, product)); await expect(fetch).toHaveBeenCalled(); expect(dispatched).toEqual([getReleaseCommitsSuccess(releaseCommits)]); fetch.mockClear(); });
控制台输出
console.log src/__tests__/sagas/release.test.js:204 { type: 'GET_RELEASE_COMMITS_SUCCESS', releaseCommits: [ { package: 'package_abc', id: 'long_id', committer: 'someone@something.com', message: 'commit msg' } ] }
解决方法
核心问题
runSaga 不会直接返回Promise,它会立即返回一个Saga任务对象。直接await runSaga无法等待Saga内部的异步操作(如fetch、response.json)执行完毕,导致断言时dispatched数组还未被填充。而控制台的console.log因事件循环机制会在后续执行,所以能看到输出,但断言已经失败。
修改后的测试代码
it('releaseCommitsSaga success', async () => { const response = responses.getReleaseCommitsResponse('success'); global.fetch = jest.fn(() => Promise.resolve({ status: 200, json: () => Promise.resolve(response), })); const dispatched = []; // 保存runSaga返回的任务对象 const task = runSaga({ dispatch: (action) => { console.log(action); dispatched.push(action); }, }, releaseCommitsSaga, getReleaseCommits(release, product)); // 等待Saga所有流程执行完成 await task.done; expect(fetch).toHaveBeenCalled(); // 注意:此处应使用测试中定义的response,而非未声明的releaseCommits expect(dispatched).toEqual([getReleaseCommitsSuccess(response)]); fetch.mockClear(); });
额外修正
测试代码中原断言使用的releaseCommits变量未在测试作用域内定义,应替换为我们mock的response(与Saga中response.json()返回的结果一致)。
内容的提问来源于stack exchange,提问作者Shubham Bhardwaj
相关产品推荐
相关产品推荐

