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

如何使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 14:57:56