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

如何用Jest测试Formik+Yup表单验证?验证失败问题求助

问题:Formik+Yup表单验证测试无法捕获错误提示

我最近在测试Formik+Yup表单验证时卡壳了——不管怎么调整测试逻辑,都没法让测试用例正确识别到表单提交后的错误提示。我写的测试代码如下:

it('displays error on submit if name is empty', async () => { 
  const wrapper = mount(<MyFormik/>) 
  const getForm = () => wrapper.find('form') 
  wrapper.find('input[name="name"]').simulate('change', { persist: () => {}, target: { name: 'name', value: '' } }) 
  wrapper.find('MyInnerForm').props().submitForm() 
  await wait(0) // 试过等待下一个事件循环甚至1秒... 
  wrapper.update() 
  expect( wrapper.update().find('.error').exists() ).toBeTruthy() // 结果一直是FALSE! 
})

不管我在提交后怎么等待、更新wrapper,Formik的errors属性始终是空对象。我查看了提交后的Formik props日志:

{ errors: {}, label: '', name: 'name', type: 'text', values: { name: '' }, touched: { name: true }, isValidating: false, status: undefined, initialValues: { name: '' }, validateOnChange: true, validateOnBlur: true } 
... submitCount: 1, isValid: false

明明submitCount是1,isValid是false,但就是没有错误信息输出。我也试过一些相关解决方案,但都没效果,wrapper好像完全没法更新错误状态。


可能的解决方案

这里有几个可以尝试的方向,帮你排查问题:

  • 触发原生表单submit事件,而非直接调用submitForm
    直接调用子组件的submitForm方法可能跳过了Formik内部的一些验证触发逻辑,试试模拟表单的原生提交事件:

    // 替换原来的submitForm调用
    getForm().simulate('submit');
    
  • 确认Yup验证规则正确配置
    检查你的MyFormik组件里的validationSchema是否真的对name字段设置了必填规则,比如:

    import * as Yup from 'yup';
    
    const validationSchema = Yup.object().shape({
      name: Yup.string().required('Name is required'), // 确保这条规则存在
    });
    
    // 在Formik组件中使用这个schema
    <Formik
      initialValues={{ name: '' }}
      validationSchema={validationSchema}
      onSubmit={/* ... */}
    >
      {/* ... */}
    </Formik>
    
  • 用waitFor替代wait(0),确保异步验证完成
    wait(0)有时候不够可靠,试试React Testing Library的waitFor来等待错误元素出现:

    import { waitFor } from '@testing-library/react';
    
    // 替换原来的wait和update逻辑
    await waitFor(() => {
      expect(wrapper.find('.error').exists()).toBeTruthy();
    });
    
  • 检查错误元素的渲染逻辑
    确保你的MyInnerForm组件正确渲染了错误信息,比如:

    // 在MyInnerForm中正确使用Formik的errors和touched
    const MyInnerForm = ({ errors, touched }) => (
      <div>
        <input name="name" />
        {touched.name && errors.name && <div className="error">{errors.name}</div>}
      </div>
    );
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:33:40