React Testing Library测试MUI DropDown无法找到option元素报错
问题根因
MUI 下拉(Select)组件的下拉选项层默认通过 Portal 挂载到全局document.body节点,且点击触发展开时,选项的渲染、弹出层入场存在异步微任务延迟。你的测试代码在点击触发按钮后同步执行元素查询,此时目标option元素还未挂载到DOM树,无论用getByRole还是getByTestId都会抛出找不到元素的错误。
修复步骤
- 替换同步的
fireEvent为@testing-library/user-event提供的用户交互模拟方法,该工具的交互逻辑更贴近真实用户操作,且所有交互方法为异步,会自动等待UI状态更新。 - 替换同步的
getBy*查询为异步的findBy*查询,该查询会默认轮询最多1000ms,直到目标元素挂载到DOM、匹配查询条件后才返回结果,刚好适配下拉选项的异步渲染逻辑。 - (可选配置)如果需要让下拉选项渲染在组件所在DOM子树、简化查询逻辑,可以给MUI Select组件传入
disablePortal属性,关闭Portal挂载行为,该配置仅在测试环境开启也可。
修复后可运行的测试代码
先安装必要依赖:npm install @testing-library/user-event --save-dev
测试代码:
import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import App from './App'; test("select", async () => { const user = userEvent.setup(); render(<App />); // 点击下拉触发按钮,等待交互和UI更新完成 const dropdownButton = screen.getByRole("button", { name: /dog name/i }); await user.click(dropdownButton); // 异步等待目标选项渲染完成后点击 const dropdownItem = await screen.findByRole("option", { name: /ninica/i }); await user.click(dropdownItem); // 可补充选中后的断言验证结果 expect(dropdownButton).toHaveTextContent(/ninica/i); });
排错提示
如果按上述修改后仍然找不到元素,可以在点击下拉按钮后加一行screen.debug()打印当前DOM结构,核对选项的可访问名称、role 是否和你的查询规则匹配,避免因为文本隐形空格、自定义role配置导致的匹配失败。
内容的提问来源于stack exchange,提问作者Flavio Silva
相关产品推荐
相关产品推荐

