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

如何Mock Ant Design的useFormInstance?测试表单字段未触碰场景

问题:Mock Ant Design的useFormInstance以测试表单字段触摸状态

场景需求

需要Mock表单实例来验证!form?.isFieldsTouched()的逻辑,且不允许将form作为props传入组件。

组件代码

export const OCRActions = ({ isEditDisabled, set }: IOCRActionsProps) => {
  const form = useFormInstance();

  return (
    <Item
      noStyle
      shouldUpdate
    >
      {() => (
        <Group>
          <Popconfirm
            title={( 
              <div className='w-[200px]'>
                Do you want to apply made changes?
                Note that they may result in receipt reprocessing.
              </div>
            )}
            okText='Yes'
            cancelText='No'
            placement='bottom'
            onConfirm={handlePatchOCR(form, ocrFormValues, patchSnapsDetails)}
            disabled={
              !form?.isFieldsTouched()
            }
          >
            <Button
              type='primary'
              loading={loading}
              disabled={
                !form?.isFieldsTouched()
              }
            >
              Save
            </Button>
          </Popconfirm>
        </Group>
      )}
    </Item>
  );
};

无效的Mock尝试

尝试以下Mock方式后,useFormInstance()返回undefined:

jest.mock('antd', () => {
  const originalModule = jest.requireActual('antd');

  return {
    ...originalModule,
    Form: {
      ...originalModule.Form,
      useFormInstance: jest.fn().mockReturnValueOnce({
        getFieldsError: jest.fn().mockReturnValueOnce(() => []),
        isFieldsTouched: jest.fn().mockReturnValueOnce(true),
      }),
    },
  };
});

解决方案

问题根源:Ant Design的useFormInstance是顶级导出,并非挂在Form对象下,之前的Mock路径错误。

方法1:直接Mock独立导出的useFormInstance

jest.mock('antd/es/form/useFormInstance', () => ({
  __esModule: true,
  default: jest.fn().mockReturnValue({
    isFieldsTouched: jest.fn().mockReturnValue(true),
    getFieldsError: jest.fn().mockReturnValue([]),
  }),
}));

方法2:在antd根模块中Mock顶级导出

jest.mock('antd', () => {
  const originalModule = jest.requireActual('antd');
  return {
    ...originalModule,
    useFormInstance: jest.fn().mockReturnValue({
      isFieldsTouched: jest.fn().mockReturnValue(true),
      getFieldsError: jest.fn().mockReturnValue([]),
    }),
  };
});

完整测试用例示例

import { render, screen } from '@testing-library/react';
import { OCRActions } from './OCRActions';
import { useFormInstance } from 'antd';

// 提前Mock useFormInstance
jest.mock('antd/es/form/useFormInstance', () => ({
  __esModule: true,
  default: jest.fn(),
}));

describe('OCRActions', () => {
  test('表单未触摸时,Save按钮禁用', () => {
    (useFormInstance as jest.Mock).mockReturnValue({
      isFieldsTouched: jest.fn().mockReturnValue(false),
    });

    render(<OCRActions isEditDisabled={false} set={jest.fn()} />);
    expect(screen.getByText('Save')).toBeDisabled();
  });

  test('表单触摸后,Save按钮启用', () => {
    (useFormInstance as jest.Mock).mockReturnValue({
      isFieldsTouched: jest.fn().mockReturnValue(true),
    });

    render(<OCRActions isEditDisabled={false} set={jest.fn()} />);
    expect(screen.getByText('Save')).not.toBeDisabled();
  });
});

关键提示

  • 确认useFormInstance的导出层级,它不属于Form组件的子属性,Mock时需匹配正确的导出路径。
  • 可通过jest.mock直接锁定具体导出文件,或在antd根模块中添加顶级Mock属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 03:57:29