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

如何用react-testing-library测试React-hook-form+MUI TextField校验?

问题出在你把trigger mock成jest.fn()了——这直接跳过了react-hook-form的原生校验触发逻辑,自然不会生成错误提示。下面是正确的测试思路和代码:

先确认组件实现(参考示例)

import { useForm, Controller } from 'react-hook-form';
import { z } from 'zod';
import { TextField } from '@mui/material';
import { zodResolver } from '@hookform/resolvers/zod';

const schema = z.object({
  input: z.string().max(10, 'Invalid input'),
});

type FormValues = z.infer<typeof schema>;

export default function MyForm() {
  const { control, handleSubmit, formState: { errors } } = useForm<FormValues>({
    resolver: zodResolver(schema),
    defaultValues: { input: '' },
  });

  const onSubmit = (data: FormValues) => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="input"
        control={control}
        render={({ field }) => (
          <TextField
            {...field}
            label="Input"
            error={!!errors.input}
            helperText={errors.input?.message}
            variant="outlined"
          />
        )}
      />
      <button type="submit">Submit</button>
    </form>
  );
}

正确的测试代码

核心是不要mock trigger,让react-hook-form的原生校验逻辑正常运行:

import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import MyForm from './MyForm';

test('shows error when input exceeds 10 characters', async () => {
  const user = userEvent.setup();
  render(<MyForm />);

  // 找到输入框并输入超过10字符的内容
  const input = screen.getByLabelText('Input');
  await user.type(input, 'abcdefghijk'); // 11个字符

  // 触发校验:RHF默认校验时机是onBlur,所以手动触发失去焦点
  await user.blur(input);

  // 等待校验完成、DOM更新后断言错误信息存在
  await waitFor(() => {
    expect(screen.getByText('Invalid input')).toBeInTheDocument();
  });

  // 另一种方式:通过提交表单触发校验
  // const submitBtn = screen.getByText('Submit');
  // await user.click(submitBtn);
  // await waitFor(() => {
  //   expect(screen.getByText('Invalid input')).toBeInTheDocument();
  // });
});

关键注意点

  • 别mock trigger:这个方法是react-hook-form内部触发校验的核心,手动mock会直接阻断校验流程,必须保留原生实现。
  • 触发对应校验时机:RHF默认校验时机是onBlur和onSubmit,测试时需要主动触发这两个行为之一,才能让zod的校验逻辑运行并生成错误信息。如果你的组件设置了mode: 'onChange',则只需输入内容后直接等待错误出现即可。
  • 用waitFor异步断言:校验和DOM更新是异步过程,必须用waitFor等待元素渲染完成后再查询。

内容的提问来源于stack exchange,提问作者Vladut Clapou

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 23:00:41