如何使用Jest测试react-hook-form的useFormContext
问题描述
我有CDOB和DOB两个组件,它们均使用Mds表单元素与react-hook-form的useFormContext。我希望为useFormContext的watch等方法编写测试用例。
组件代码如下:
CDOB组件
export default function CDOB(props){ const { addr } = props; const { watch } = useFormContext(); const code = watch(addr) ; const getMsg =() => { if(code == 'AL'){ return 'Invalid state'} else {return 'Invalid entry'} } return( <DOB age={getMsg()}/>) }
DOB组件
export default function DOB(props){ const { age } = props; const { watch, setValue } = useFormContext(); const code = watch('addr') ; // 修正原代码遗漏的引号,addr应为表单字段名 const getMsg =() => { if(code == 'AL'){ return 'Invalid state'} else {return 'Invalid entry'} } return ( <MdsTextInput onChange={props.onChange} // 其他属性 /> ) }
请问如何使用Jest测试useFormContext的watch方法?
测试实现方案
要测试useFormContext的watch方法,核心是通过FormProvider提供模拟的表单上下文,控制watch的返回值,验证组件逻辑是否符合预期。以下是具体步骤:
1. 基础准备
确保测试环境已安装@testing-library/react、jest及react-hook-form依赖。
2. 测试CDOB组件
CDOB的核心逻辑是根据watch(addr)的返回值生成提示文本,传递给DOB组件。测试用例如下:
import React from 'react'; import { render, screen } from '@testing-library/react'; import { FormProvider, useForm } from 'react-hook-form'; import CDOB from './CDOB'; // 模拟DOB组件,避免依赖其内部实现 jest.mock('./DOB', () => (props) => <div data-testid="dob-component">{props.age}</div>); describe('CDOB Component', () => { it('传递给DOB的age为"Invalid state"当watch返回"AL"时', () => { // 创建表单上下文,预设字段值 const formMethods = useForm({ defaultValues: { testAddr: 'AL' } }); render( <FormProvider {...formMethods}> <CDOB addr="testAddr" /> </FormProvider> ); // 验证传递给DOB的属性是否正确 expect(screen.getByTestId('dob-component')).toHaveTextContent('Invalid state'); }); it('传递给DOB的age为"Invalid entry"当watch返回非AL值时', () => { const formMethods = useForm({ defaultValues: { testAddr: 'NY' } }); render( <FormProvider {...formMethods}> <CDOB addr="testAddr" /> </FormProvider> ); expect(screen.getByTestId('dob-component')).toHaveTextContent('Invalid entry'); }); });
3. 测试DOB组件
DOB组件调用watch('addr')生成提示,我们需要验证watch不同返回值下的逻辑,以及表单值更新后的响应:
import React from 'react'; import { render, screen } from '@testing-library/react'; import { FormProvider, useForm } from 'react-hook-form'; import DOB from './DOB'; // 模拟MdsTextInput组件 jest.mock('./MdsTextInput', () => (props) => <input data-testid="mds-input" onChange={props.onChange} />); // 先修改DOB组件,添加测试用的提示文本节点(方便验证): // return ( // <> // <div data-testid="dob-message">{getMsg()}</div> // <MdsTextInput onChange={props.onChange} /> // </> // ) describe('DOB Component', () => { it('显示"Invalid state"当watch返回"AL"时', () => { const formMethods = useForm({ defaultValues: { addr: 'AL' } }); render( <FormProvider {...formMethods}> <DOB /> </FormProvider> ); expect(screen.getByTestId('dob-message')).toHaveTextContent('Invalid state'); }); it('表单值更新后提示文本同步变化', async () => { const formMethods = useForm({ defaultValues: { addr: 'CA' } }); render( <FormProvider {...formMethods}> <DOB /> </FormProvider> ); // 更新表单字段值 await formMethods.setValue('addr', 'AL'); // 验证提示文本是否更新 expect(screen.getByTestId('dob-message')).toHaveTextContent('Invalid state'); }); });
关键注意事项
- 模拟依赖组件:用
jest.mock模拟子组件或第三方组件,确保测试只关注当前组件的watch逻辑,不受外部实现干扰。 - FormProvider包裹:所有使用
useFormContext的组件必须包裹在FormProvider中,并传入模拟的formMethods,否则无法获取上下文。 - 验证核心逻辑:测试重点是
watch返回不同值时,组件的输出(props、UI文本等)是否符合预期,而非watch方法本身的实现。
内容的提问来源于stack exchange,提问作者CoderInUi
相关产品推荐
相关产品推荐

