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

React组件单元测试失败:点击提交按钮后无法找到确认模态框按钮

React组件单元测试失败:点击提交按钮后无法找到确认模态框按钮

我来帮你分析下这个问题的根源,以及怎么解决它~

问题原因

你遇到的核心问题是React状态更新的异步性:当你点击提交按钮后,组件内部调用setIsModalOpen(true)来显示模态框,但这个状态更新并不是同步完成的,DOM不会立刻渲染出模态框。而你用的queryByTestId是同步查找方法,它会马上执行,这时候模态框还没出现在DOM里,自然就会报“unable to find element”的错误。

另外,虽然你在测试里验证了openConfirmationModal被调用,但组件的模态框显示其实是由内部状态isModalOpen控制的,这个状态更新的异步性才是导致找不到元素的关键。

解决方案

你需要用异步查询方法来等待模态框元素加载完成,这里有两种常用的方式:

方式1:使用findByTestId(推荐)

findByTestId是queryByTestId的异步版本,它会自动等待元素出现在DOM中(默认超时时间是1000ms),非常适合这种场景。修改你的测试代码如下:

it('text field', async () => {
 const props = {
   openConfirmationModal: jest.fn()
  }

  const { queryByTestId, findByTestId } = render(
    <FormInputs
      openConfirmationModal={props.openConfirmationModal}
    />
  );

  const input = queryByTestId('input-component-amount') as HTMLInputElement;
  expect(input).toBeInTheDocument();

  fireEvent.change(input, { target: { value: '123' } }); // 注意这里传字符串,和组件状态类型保持一致

  const textArea = queryByTestId('textarea-component-textfield') as HTMLTextAreaElement;
  expect(textArea).toBeInTheDocument();
  fireEvent.change(textArea, { target: { value: 'This is some text!' } });

  const submitButton = queryByTestId('button') as HTMLButtonElement;
  expect(submitButton).toBeInTheDocument();
  expect(submitButton).toBeEnabled();

  fireEvent.click(submitButton);

  expect(props.openConfirmationModal).toHaveBeenCalledTimes(1);

  // 改用异步的findByTestId,并且await等待元素出现
  const submitModalButton = await findByTestId('confirmation-modal-submit-button') as HTMLButtonElement;
  expect(submitModalButton).toBeInTheDocument();
});

方式2:使用waitFor包裹queryByTestId

如果你还是想用queryByTestId,可以把它放在waitFor里,等待查询结果符合预期:

// ... 前面的测试代码保持不变

fireEvent.click(submitButton);

expect(props.openConfirmationModal).toHaveBeenCalledTimes(1);

// 用waitFor等待DOM更新完成,直到找到目标元素
await waitFor(() => {
  const submitModalButton = queryByTestId('confirmation-modal-submit-button') as HTMLButtonElement;
  expect(submitModalButton).toBeInTheDocument();
});

额外提示

注意组件里的amount状态是string类型,所以测试中给input传值时,最好传字符串'123'而不是数字123,避免类型不匹配的隐性问题(虽然fireEvent会自动转换,但保持类型一致能让测试更严谨)。

备注:内容来源于stack exchange,提问作者new coderrrr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 13:38:01