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

如何为接收Formik状态作为props的组件编写测试?

问题解决:React Testing Library测试ComponentB时的钩子调用错误

错误原因

测试代码里直接在test函数(普通JavaScript函数)中调用useFormik钩子,违反了React钩子的调用规则——钩子只能在React函数组件的顶层或自定义钩子内部调用,因此触发Invalid hook call错误。

解决方案

ComponentB仅依赖传入的formikBag props,不需要在测试中真实调用useFormik,直接构造符合结构的模拟对象即可,有两种常用方式:

方案一:手动构造Mock的formikBag

直接模拟ComponentB用到的属性,简单高效,适合仅测试渲染逻辑的场景:

// ComponentB测试代码修改后
test('should render ComponentB', async () => {
  // 构造mock的formikBag,包含组件用到的属性
  const mockFormikBag = {
    values: { name: "xxx", id: 1 },
    setFieldValue: jest.fn(), // 如果组件用到该方法,用jest.fn()模拟
    setValues: jest.fn()
  };

  const { asFragment } = render(
      <ThemeProvider>
        <MockedProvider mocks={[mockQueryMe]}>
          <ComponentB formikBag={mockFormikBag} />
        </MockedProvider>
      </ThemeProvider>
  );
  await waitFor(() => {
    expect(asFragment()).toMatchSnapshot();
  });
});

方案二:用临时组件包裹调用useFormik

如果需要更贴近真实场景(比如验证formik的状态变化对ComponentB的影响),可以在测试中定义一个临时的React函数组件,在内部调用useFormik后传递给ComponentB:

// ComponentB测试代码修改后
test('should render ComponentB with real formik context', async () => {
  // 定义临时组件,内部调用useFormik
  const TestWrapper = () => {
    const formikBag = useFormik({
      initialValues: { name: "xxx", id: 1 },
    });
    return <ComponentB formikBag={formikBag} />;
  };

  const { asFragment } = render(
      <ThemeProvider>
        <MockedProvider mocks={[mockQueryMe]}>
          <TestWrapper />
        </MockedProvider>
      </ThemeProvider>
  );
  await waitFor(() => {
    expect(asFragment()).toMatchSnapshot();
  });
});

说明

  • 方案一适合快速验证组件的渲染结果,无需依赖Formik的真实逻辑;
  • 方案二更适合测试组件与Formik状态联动的场景,比如修改值后组件的更新逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 09:35:06