You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 17:06:50