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

React Jest服务执行代码覆盖率测试(Mock Axios调用)问题排查

Jest测试React函数的问题与修复

需求

作为React和Jest新手,需要测试loadUsersData函数,验证以下内容:

  • callback、dispatch、clearMessage、errMessage是否按逻辑执行
  • service.fetchUsers是否被正确调用,且能返回Mock数据
  • 覆盖所有代码分支以提升覆盖率

待测试代码

export const loadUsersData = ({requId, dataId, callback, dispatch, clearMessage, errMessage, service}) => {
    const reqObj = {requId, dataId};
    dispatch(clearMessage());
    service.fetchUsers(reqObj).then((response) => {
        const accData = response?.data?.accNumbers ? response.data.accNumbers : [];
        if(accData.length) {
            return callback(accData);
       } else {
            dispatch(errMessage("No data found"));
        }
    }).catch((error) => {
        dispatch(errMessage("Service failed to load data"));
        return callback(accData); // 注意:这里accData未定义,属于原代码bug
    });
}

原测试用例的问题

你尝试的测试代码存在几个问题:

  1. 语法错误:async()={应为async () => {;调用函数时错误使用loadUsersData = (...),应该直接调用loadUsersData(...)
  2. 异步未等待:service.fetchUsers是异步操作,测试未等待Promise完成就执行断言,导致断言时机错误
  3. spyOn使用不当:service.fetchUsers已经是Jest mock函数,不需要再用jest.spyOn,直接给mock函数设置返回值即可

原测试代码:

it("fetch data", async()={ // 语法错误:async()={ 应为 async () => {
    const reqObj = {requId:"123", dataId:"ABC"};
    const callback = jest.fn();
    const dispatch = jest.fn();
    const clearMessage = jest.fn();
    const errMessage = jest.fn();
    const service = {fetchUsers : jest.fn()}
    loadUsersData = ({requId:"123", dataId:"ABC", callback, dispatch, clearMessage, errMessage, service}); // 错误:不应赋值,直接调用函数
    expect(dispatch).toHaveBeenCalled();
    expect(service.fetchUsers).toHaveBeenCalledWith(reqObj);
});

使用jest.spyOn报错的原因:本地创建的service对象中,fetchUsers已经是mock函数,spyOn需要监听已存在的非mock方法,直接给service.fetchUsers设置mockResolvedValue即可。

修复后的完整测试用例

以下是覆盖所有分支的测试代码,包含三个核心场景:

场景1:Service返回有效数据

it("调用service获取到有效数据时,执行callback", async () => {
    const reqObj = { requId: "123", dataId: "ABC" };
    const mockAccData = ["acc1", "acc2"];
    const callback = jest.fn();
    const dispatch = jest.fn();
    const clearMessage = jest.fn();
    const errMessage = jest.fn();
    const service = {
        fetchUsers: jest.fn().mockResolvedValue({
            data: { accNumbers: mockAccData }
        })
    };

    await loadUsersData({ requId: reqObj.requId, dataId: reqObj.dataId, callback, dispatch, clearMessage, errMessage, service });

    // 验证dispatch调用了clearMessage
    expect(dispatch).toHaveBeenCalledWith(clearMessage());
    // 验证service.fetchUsers被传入正确参数
    expect(service.fetchUsers).toHaveBeenCalledWith(reqObj);
    // 验证callback被传入正确数据
    expect(callback).toHaveBeenCalledWith(mockAccData);
    // 验证errMessage未被调用
    expect(errMessage).not.toHaveBeenCalled();
});

场景2:Service返回空数据

it("调用service返回空数据时,触发无数据提示", async () => {
    const reqObj = { requId: "123", dataId: "ABC" };
    const callback = jest.fn();
    const dispatch = jest.fn();
    const clearMessage = jest.fn();
    const errMessage = jest.fn();
    const service = {
        fetchUsers: jest.fn().mockResolvedValue({
            data: { accNumbers: [] }
        })
    };

    await loadUsersData({ requId: reqObj.requId, dataId: reqObj.dataId, callback, dispatch, clearMessage, errMessage, service });

    expect(dispatch).toHaveBeenCalledWith(errMessage("No data found"));
    expect(callback).not.toHaveBeenCalled();
});

场景3:Service请求失败

it("service请求失败时,触发错误提示", async () => {
    const reqObj = { requId: "123", dataId: "ABC" };
    const callback = jest.fn();
    const dispatch = jest.fn();
    const clearMessage = jest.fn();
    const errMessage = jest.fn();
    const service = {
        fetchUsers: jest.fn().mockRejectedValue(new Error("请求失败"))
    };

    await loadUsersData({ requId: reqObj.requId, dataId: reqObj.dataId, callback, dispatch, clearMessage, errMessage, service });

    expect(dispatch).toHaveBeenCalledWith(errMessage("Service failed to load data"));
    // 注意:原代码catch块中使用了未定义的accData,会导致报错,建议修复为callback([])或其他合理逻辑
});

额外注意事项

  • 原代码的catch块中使用了accData变量,但该变量仅在then块中定义,会导致未定义错误,建议修复为callback([])或其他合理逻辑
  • 所有异步测试必须使用await等待Promise完成,否则断言会在异步操作结束前执行,导致结果不符合预期

内容的提问来源于stack exchange,提问作者Sam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 07:25:31