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

React 16:使用Jest和Enzyme测试handleChange事件报错解决

问题:Jest+Enzyme测试React组件handleChange事件时触发TypeError

在测试React组件下拉按钮点击触发的handleChange事件时,出现错误TypeError: Cannot read property 'attributes' of undefined,相关代码及报错如下:

组件代码(Component.js)

handleChange = event => {
  if (event.target.attributes["value"]) {
    window.dataLayer.push({
      event: "customEvent",
      category: "dropdown",
      action: "select",
      label: "ABC",
      attribute1: "attribute1Value",
      attribute2: "attribute2Value",
      attribute3: "attribute3Value",
      attribute4: event.target.attributes["value"].value.toLowerCase()
    });
    this.setState({ stateName: event.target.attributes["value"].value });
  }
};

测试代码(Component.test.js)

it.only("should call handleChange reponse", () => {
  const handleChange = jest.fn();
  const wrapper = shallow(
    <ComponentName
      triggerRequest={{
        triggers: {
          coverage: "ABC"
        }
      }}
    />
  );

  wrapper.find(".dropdown").simulate("click");
  wrapper.instance().handleChange({});
  expect(handleChange.mock.calls.length).toBe(1);
  // expect(handleChange).toHaveBeenCalled();
});

报错信息

TypeError: Cannot read property 'attributes' of undefined

  213 |
  214 |   handleChange = event => {
> 215 |     if (event.target.attributes["value"]) {
      |                      ^
  216 |       window.dataLayer.push({
  217 |         event: "custom_event",
  218 |         category: "dropdown",

问题原因

  1. 事件对象不完整:测试中直接传入{}作为event参数,该对象没有target属性,导致event.target为undefined,访问event.target.attributes时触发报错。
  2. 测试逻辑错误:自定义的handleChange = jest.fn()没有替换组件实例的同名方法,测试中实际调用的是组件原生的handleChange,因此expect(handleChange.mock.calls.length).toBe(1)永远不会成立。

解决方法

1. 构造合法的事件对象

调用handleChange时,传入包含target和attributes结构的模拟事件对象:

const mockEvent = {
  target: {
    attributes: {
      value: { value: "TEST_VALUE" }
    }
  }
};

2. 正确监听组件的handleChange方法

用jest.spyOn监听组件实例的handleChange方法,替代自定义的空jest.fn:

const wrapper = shallow(<ComponentName ...props />);
const handleChangeSpy = jest.spyOn(wrapper.instance(), 'handleChange');
// React 16+类组件需强制更新,确保spy生效
wrapper.instance().forceUpdate();

3. 修正后的完整测试代码

it.only("should call handleChange correctly", () => {
  // 构造模拟事件对象
  const mockEvent = {
    target: {
      attributes: {
        value: { value: "TEST_VALUE" }
      }
    }
  };

  const wrapper = shallow(
    <ComponentName
      triggerRequest={{
        triggers: {
          coverage: "ABC"
        }
      }}
    />
  );

  // 监听组件的handleChange方法
  const handleChangeSpy = jest.spyOn(wrapper.instance(), 'handleChange');
  wrapper.instance().forceUpdate();

  // 触发方法
  wrapper.instance().handleChange(mockEvent);
  // 若点击事件会绑定调用handleChange,也可改用:
  // wrapper.find(".dropdown").simulate("click", mockEvent);

  // 断言方法被调用
  expect(handleChangeSpy).toHaveBeenCalledTimes(1);
  // 可选:断言传入的参数是否正确
  expect(handleChangeSpy).toHaveBeenCalledWith(mockEvent);
});

4. 优化组件代码(可选,避免生产环境报错)

在组件的handleChange中添加空值判断,防止实际场景中event或event.target为undefined的情况:

handleChange = event => {
  if (event?.target?.attributes?.["value"]) {
    // 原逻辑代码
  }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 05:28:11