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

如何在Jest测试中修改React useState Hook的状态值?

问题排查与解决方案

你现有代码的错误点如下:

  • 拼写错误:自定义初始状态里的键写为signUpTyp,缺少末尾的e,和实际定义的signUpType不匹配
  • 结构错误:给useState返回的第一个参数额外套了一层数组,原state是纯对象,会导致组件内读取form.signUpType失败
  • 模拟的setForm为空对象,组件后续如果调用更新方法会直接报错
  • 直接覆盖React.useState的方式不严谨,如果组件内有多个useState,所有hook都会被替换为同一个模拟值,逻辑完全混乱

推荐方案:模拟用户操作切换注册类型(无需mock hook)

单元测试优先选择贴近用户实际使用的写法,避免和组件内部实现耦合。你页面上肯定存在切换手机号/邮箱注册的交互按钮,直接模拟点击即可:

it("Email validation", () => {
  const email = "sample.s@abc.com";
  const tree = mount(
    <Provider store={configureStore}>
      <SignIn />
    </Provider>
  );
  // 替换为你实际的切换按钮选择器,优先用data-testid标记测试元素
  tree.find('[data-testid="switch-to-email-btn"]').simulate('click');
  
  // 验证邮箱输入框显示、值符合预期
  expect(tree.find('CustomTextInput[attrName="email"]').exists()).toBeTruthy();
  expect(tree.find('CustomTextInput[attrName="email"]').prop("value")).toBe("");
  expect(email).toMatch(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,})+$/);
});

该方案不受内部state实现方式影响,哪怕后续你把useState替换为useReducer,测试用例也不需要修改,可靠性更高。

可选方案:直接mock useState

如果确实需要强制修改初始state值,可按以下正确写法实现:

it("Email validation", () => {
  const email = "sample.s@abc.com";
  // 构造和原state完全一致的模拟数据
  const mockForm = {
    email: "",
    phoneNumber: "",
    password: "",
    signUpType: SignUpType.EMAIL
  };
  // 用spyOn模拟单个useState调用,避免影响其他测试
  const useStateSpy = jest.spyOn(React, 'useState')
    // 按组件内useState调用顺序,第一个调用的就是form state,返回模拟值
    .mockReturnValueOnce([mockForm, jest.fn()]);

  const tree = mount(
    <Provider store={configureStore}>
      <SignIn />
    </Provider>
  );

  expect(tree.find('CustomTextInput[attrName="email"]').prop("value")).toBe("");
  expect(email).toMatch(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,})+$/);

  // 测试完成后清除mock,避免污染其他用例
  useStateSpy.mockRestore();
});

注意:如果组件内有多个useState,需要按调用顺序依次用mockReturnValueOnce设置每个hook的返回值,顺序错误会导致取值混乱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 14:36:01