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

React JS API调用Jest单元测试报错,如何修复并编写通用测试用例?

React API调用单元测试报错修复及可复用方案

核心错误定位

你的测试用例失败的核心原因是断言时误用了数组索引:你mock的response.json()返回的是单个车辆对象,getCar方法直接将该对象返回,而你的测试代码里写的是expect(data[0]).toEqual(testData),访问不存在的0索引会得到undefined,自然无法通过断言。
如果你的实际接口返回的是车辆数组,你需要把mock的testData包裹在数组中即可。

修复后的测试代码

// car.test.js 修复后完整代码
import { getCar } from "../Service/MainScreen/Cars/Car";
import config from "../../../Config/Api";

describe("Car API Call function", () => {
  // 单测执行后清空所有mock状态,避免用例间互相影响
  afterEach(() => {
    jest.clearAllMocks();
  });

  test("正常请求时返回正确的车辆数据", async () => {
    // 若接口实际返回数组,此处改为 const testData = [{...你的原有数据}]
    const testData = {
      id: 186,
      plate_number: "WW12345",
      status_display: "Aktywny",
      driver_name: "Jakub Nowak",
      driver_id: 181,
      created_at: "2021-08-12T09:07:30Z",
      vin: "WBADM123123123123",
      brand: "Ford",
      model: "Focus",
      "Brand-Model": "Ford/Focus",
      production: "2016",
      registration: "01-12-2020",
      insurance_date: "06-06-2023",
      has_registration_docs: true,
      has_policy_status: true,
      has_certificate: true,
      has_green_card: true,
      has_vehicle_card: true,
      has_car_picture: true,
      fleet_entry: "20-04-2018",
      monitoring_start: "12-08-2021",
      status: "Aktywny",
      Estimaed_distance: 29500,
      Estimaed_fuel: 1475,
      average_fuel: 5,
      claim: 1,
      cost: 1000,
    };

    const mockResponse = { json: jest.fn().mockResolvedValueOnce(testData) };
    global.fetch = jest.fn().mockResolvedValueOnce(mockResponse);

    const result = await getCar();
    // 校验fetch调用参数符合预期,避免配置错误
    expect(fetch).toHaveBeenCalledTimes(1);
    expect(fetch).toHaveBeenCalledWith(config.fakeapi.car, config.fakeHead);
    // 若接口返回数组,此处改为 expect(result[0]).toEqual(testData)
    expect(result).toEqual(testData);
  });

  test("请求异常时正确执行错误处理逻辑", async () => {
    const mockError = new Error('网络请求失败');
    global.fetch = jest.fn().mockRejectedValueOnce(mockError);
    // 拦截console.log避免污染测试输出
    const consoleSpy = jest.spyOn(console, 'log').mockImplementation();

    await getCar();
    expect(fetch).toHaveBeenCalledTimes(1);
    expect(consoleSpy).toHaveBeenCalledWith(mockError);
    // 恢复console原生实现
    consoleSpy.mockRestore();
  });
});

可复用API测试逻辑封装

你可以将通用的单测逻辑抽为工具函数,所有API调用的测试都可以直接复用:

// 新增工具文件:src/utils/test/apiTestHelpers.js
/**
 * 测试API接口正常请求场景
 * @param {Function} apiFunc 待测试的API方法
 * @param {Array} apiArgs 调用API方法时传入的参数数组
 * @param {any} mockData 模拟的接口返回数据
 * @param {Array} expectedFetchParams 预期fetch接收的参数 [url, 请求配置]
 */
export async function testApiSuccess(apiFunc, apiArgs = [], mockData, expectedFetchParams) {
  const mockResponse = { json: jest.fn().mockResolvedValueOnce(mockData) };
  global.fetch = jest.fn().mockResolvedValueOnce(mockResponse);

  const result = await apiFunc(...apiArgs);
  expect(fetch).toHaveBeenCalledTimes(1);
  if (expectedFetchParams) {
    expect(fetch).toHaveBeenCalledWith(...expectedFetchParams);
  }
  expect(result).toEqual(mockData);
}

/**
 * 测试API接口异常请求场景
 * @param {Function} apiFunc 待测试的API方法
 * @param {Array} apiArgs 调用API方法时传入的参数数组
 * @param {Error} mockError 模拟的错误对象
 */
export async function testApiError(apiFunc, apiArgs = [], mockError = new Error('请求失败')) {
  global.fetch = jest.fn().mockRejectedValueOnce(mockError);
  const consoleSpy = jest.spyOn(console, 'log').mockImplementation();

  await apiFunc(...apiArgs);
  expect(consoleSpy).toHaveBeenCalledWith(mockError);
  consoleSpy.mockRestore();
}

复用示例(以测试getDriver接口为例)

// driver.test.js
import { getDriver } from "../Service/Driver";
import config from "../../../Config/Api";
import { testApiSuccess, testApiError } from "src/utils/test/apiTestHelpers";

describe("Driver API 测试", () => {
  afterEach(() => jest.clearAllMocks());

  test("正常请求返回司机数据", async () => {
    const mockData = { id: 181, name: "Jakub Nowak" };
    await testApiSuccess(
      getDriver,
      [181], // 调用getDriver传入的司机ID参数
      mockData,
      [config.fakeapi.driver(181), config.fakeHead] // 预期fetch调用的参数
    );
  });

  test("请求异常正常处理", async () => {
    await testApiError(getDriver, [181]);
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 16:09:03