React测试:如何mock react-hook-form的useFormContext方法?
解决方案
方案1:使用FormProvider包裹测试组件(优先推荐)
该方案完全模拟生产环境中父组件调用子组件的逻辑,无需mock hook,测试结果更准确:
import { useForm, FormProvider } from 'react-hook-form'; // 导入你的类型定义 import type { CustomerProfileFormData } from '你的类型定义文件路径'; it('should render properly', () => { // 初始化表单实例,和父组件实际用法一致 const formMethods = useForm<CustomerProfileFormData>(); render( <FormProvider {...formMethods}> <AddressDetails isEdit={false} /> </FormProvider> ); expect(screen.getByTestId('address-details')).toBeInTheDocument(); });
方案2:手动mock useFormContext hook
如果需要隔离表单逻辑做单独测试,可以直接mock hook返回值:
- 在测试文件顶部mock react-hook-form模块:
jest.mock('react-hook-form', () => ({ ...jest.requireActual('react-hook-form'), useFormContext: jest.fn(() => ({ // 按子组件实际用到的方法补齐mock内容 register: jest.fn(), // 如果用到其他方法也可以在这里添加,比如: // handleSubmit: jest.fn(), // formState: { errors: {} } })) }));
- 如果不同测试用例需要自定义返回值,可以单独覆盖:
import { useFormContext } from 'react-hook-form'; it('should render error when address is invalid', () => { (useFormContext as jest.Mock).mockReturnValueOnce({ register: jest.fn(), formState: { errors: { address: { message: '地址不能为空' } } } }); render(<AddressDetails isEdit={false} />); // 你的断言逻辑 });
注意事项
- 如果你选择方案2,必须保证mock返回值包含所有子组件中从useFormContext解构出来的属性,否则依然会出现解构报错
- 没有特殊隔离需求的场景下优先使用方案1,更贴近真实运行逻辑,维护成本更低
内容的提问来源于stack exchange,提问作者Amit Uppal
相关产品推荐
相关产品推荐

