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

测试componentDidMount时axiosRequest Mock返回undefined问题排查

测试componentDidMount时mock axiosRequest始终返回undefined,问题出在哪?

我想测试组件的componentDidMount生命周期方法,确保axiosRequest函数返回一个数组,但不管怎么mock这个函数,它始终返回undefined,我忽略了什么?


axiosRequest包装函数

export const axiosRequest = (type, url, body, headers) => {
  return axios[type](url,
  {
    ...body,
    sharedLinkToken: store.getState()?.token ? store.getState()?.token : null,
    activeWorkspace: body?.activeWorkspace ? body?.activeWorkspace : 
      store.getState()?.auth?.org?.activeWorkspace,
  },
  { ...headers },
 ).then((res) => res?.data);
};

componentDidMount中的调用代码

async componentDidMount() {
  try {
    const fieldTypes = await axiosRequest('post', '/api/custom-fields/types');
    console.log('fieldTypes: ', fieldTypes);
    this.setState({ fieldTypes });
  } catch (e) {
    this.setState({ disable: true });
  }
}

我的测试代码(尝试过多种mock方式)

import * as axiosRequest from '../../../../utilities/utilities';
let mockAxiosRequest;
// jest.mock('axios');
// jest.mock('../../../../utilities/utilities', () => ({
//   axiosRequest: jest.fn(),
// }));
beforeEach(() => {
  props = {};
  wrapper = shallow(<CreateCustomField {...props} />);
  instance = wrapper.instance();
  mockAxiosRequest = jest.spyOn(axiosRequest, 'axiosRequest');
});

it('Should find the wrapper', async () => {
  mockAxiosRequest.mockResolvedValue(['stuff']);
  // mockAxiosRequest.mockResolvedValue(() => ['stuff']);
  // mockAxiosRequest.mockResolvedValueOnce(['stuff']);
  // mockAxiosRequest.mockReturnThis(['stuff']);
  // mockAxiosRequest.mockImplementation(() => ['stuff']);
  // mockAxiosRequest.mockImplementation(() => Promise.resolve(['stuff']));
  expect(wrapper.find('.create-custom-fields-modal').length).toBe(1);
  expect(instance.state.fieldTypes.length).toBe(1);
});

问题根源及解决方法

核心问题

  1. mock时机滞后:你是在组件实例创建完成后才mockaxiosRequest,但componentDidMount在shallow渲染组件时已经执行,此时mock还未生效,实际调用的是原函数,导致返回undefined。
  2. 异步测试未等待:测试逻辑是异步的,但你没有等待componentDidMount中的异步请求完成就断言状态,此时setState还未执行,fieldTypes仍是初始值。

修正后的测试代码

import * as axiosRequest from '../../../../utilities/utilities';
let mockAxiosRequest;
let props;
let wrapper;
let instance;

// 提前mock整个模块,确保组件导入时就使用mock函数
jest.mock('../../../../utilities/utilities', () => ({
  axiosRequest: jest.fn(),
}));

beforeEach(() => {
  props = {};
  // 先设置mock返回值,再创建组件
  mockAxiosRequest = axiosRequest.axiosRequest;
  mockAxiosRequest.mockResolvedValue(['stuff']);
  wrapper = shallow(<CreateCustomField {...props} />);
  instance = wrapper.instance();
});

it('Should fetch field types and update state', async () => {
  // 等待componentDidMount中的异步操作完成
  await instance.componentDidMount();
  // 强制更新组件,确保state变化同步到wrapper
  wrapper.update();
  
  expect(wrapper.find('.create-custom-fields-modal').length).toBe(1);
  expect(instance.state.fieldTypes).toEqual(['stuff']);
  expect(mockAxiosRequest).toHaveBeenCalledWith('post', '/api/custom-fields/types');
});

关键调整点

  • 用jest.mock提前mock整个工具模块,替代jest.spyOn,保证组件从一开始就使用mock函数。
  • 在创建组件之前配置mock的返回值,确保componentDidMount执行时mock已生效。
  • 显式调用await instance.componentDidMount()等待异步操作完成,再进行断言。
  • 调用wrapper.update()触发组件重新渲染,避免断言时拿到旧的state。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 17:54:28