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
相关产品推荐
相关产品推荐

