React Testing Library测试useForm表单输入后错误提示不消失问题
你遇到的问题核心有两个:
- React Hook Form 默认的校验触发时机为
onSubmit,也就是只有提交表单时才会执行校验,你修改输入框值后不会自动触发重新校验,因此错误提示不会消失。 - 测试代码的查询逻辑和断言逻辑存在问题,导致测试无法匹配预期行为。
第一步:调整React Hook Form配置
在初始化useForm时增加mode参数,指定校验触发时机为输入值变化时触发:
const { register, handleSubmit, formState: { errors }, } = useForm({ resolver: yupResolver(schema), mode: 'onChange' // 输入值变化时自动重新校验 });
如果不想全局修改校验触发时机,也可以在修改输入值后手动调用trigger()方法触发校验。
第二步:修正测试代码
测试代码存在3个需要调整的点:
- 不需要手动用
act()包裹fireEvent,React Testing Library的事件触发方法已经内部处理了act逻辑,额外包裹反而可能导致状态更新异常 - 提交表单后需要先等待错误提示渲染完成,再修改输入值
- 修改输入值后不能用
findAllByTestId查询错误元素,如果错误已经消失,该异步查询会超时失败,应该用queryAllByTestId,查询不到对应元素会返回空数组,不会抛出异常
修改后的测试代码如下:
test("Correct input does not give error anymore", async () => { render( <ThemeProvider theme={theme}> <LoginForm /> </ThemeProvider> ); const button = screen.getByDisplayValue(/Login/i); // 点击提交触发校验 fireEvent.click(button); // 等待错误提示渲染完成 await screen.findAllByTestId("error"); const usernameInput = screen.getByLabelText(/username:/i); const passwordInput = screen.getByLabelText(/password:/i); // 输入合法值,自动触发校验 fireEvent.change(usernameInput, { target: { value: "test123" } }); fireEvent.change(passwordInput, { target: { value: "123456" } }); // 校验输入值正确 expect(usernameInput.value).toBe("test123"); expect(passwordInput.value).toBe("123456"); // 校验错误提示已经全部消失 expect(screen.queryAllByTestId("error")).toHaveLength(0); });
额外注意点
你在password输入框的register参数中额外写了{ required: true },这和Yup校验规则重复,建议删除避免冲突。
内容的提问来源于stack exchange,提问作者jakzar
相关产品推荐
相关产品推荐

