You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Jest测试问题:Antd表单validateFields后props函数调用断言失败

解决Antd表单validateFields回调中函数调用的测试断言失败问题

我来帮你分析下问题根源,并给出可行的解决方案:

问题核心原因

Ant Design的form.validateFields方法是异步执行的——当你传入回调函数时,它会在表单验证逻辑完成(可能包含异步校验规则)后才触发回调。而你的测试在模拟表单提交后立刻执行断言,此时回调里的changeMasterbotParameters还没来得及被调用,自然导致断言失败。

而你放在validateFields外部的函数调用是同步执行的,所以测试能正常捕获到调用行为。


解决方案

方案1:改用validateFields的Promise版本(推荐)

Antd的validateFields如果不传递回调函数,会返回一个Promise,这样你可以用async/await处理异步逻辑,让测试更容易同步。

修改组件代码:

async handleSubmit(event: React.FormEvent<HTMLFormElement>) {
  event.preventDefault();
  try {
    // 等待表单验证完成,获取有效值
    const values = await this.props.form.validateFields();
    console.log('Received values of form: ', values);
    // 验证通过后调用目标函数
    this.props.changeMasterbotParameters({
      name: values.name,
      greetingMessages: values.greetingMessages,
      disambiguationMessages: values.disambiguationMessages,
      avatar: '',
      rgpd: { nbofDays: values.rgpdNbOfDays }
    });
  } catch (err) {
    message.warning('Oh no ! Some entries are missing !');
    console.error('error:', err);
  }
};

修改测试代码:

将测试函数改为async,并用await等待表单提交的异步逻辑完成:

it('+++ check saveMasterbotParameters function is called when clicking on save', async () => {
  // 模拟表单提交,等待异步逻辑完成
  await wrapper.find(Form).simulate('submit', { preventDefault: jest.fn() });
  
  // 此时validateFields的Promise已resolve,函数已被调用
  expect(props.changeMasterbotParameters).toHaveBeenCalled();
});

方案2:不修改组件,刷新Pending Promise

如果不想改动组件的回调式写法,可以在测试中手动刷新所有pending的Promise,确保validateFields的回调有机会执行。

步骤:

  1. 定义一个工具函数刷新Promise:
const flushPromises = () => new Promise(resolve => setImmediate(resolve));
  1. 在测试中调用这个函数,等待异步回调执行:
it('+++ check saveMasterbotParameters function is called when clicking on save', async () => {
  // 模拟表单提交
  wrapper.find(Form).simulate('submit', { preventDefault: jest.fn() });
  
  // 等待所有异步操作(包括validateFields的回调)完成
  await flushPromises();
  
  // 现在断言函数已被调用
  expect(props.changeMasterbotParameters).toHaveBeenCalled();
});

额外关键注意事项

  1. 确保表单验证通过:如果表单字段有错误(比如必填项为空),validateFields的回调中!err为false,不会执行changeMasterbotParameters。测试前可以用form.setFieldsValue设置有效值:
beforeEach(() => {
  jest.clearAllMocks();
  // 设置表单字段为有效状态,避免验证失败
  props.form.setFieldsValue({
    name: 'Test Bot',
    greetingMessages: ['Hello!'],
    disambiguationMessages: ['Sorry, I didn\'t get that.'],
    rgpdNbOfDays: 90
  });
});
  1. 确认Form组件的模拟正确:确保你使用的mount能正确渲染Antd的Form组件,并且form prop已经正确传递给组件。

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

火山引擎 最新活动