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
相关产品推荐
相关产品推荐

