使用React Testing Library与Jest测试hover时无法获取预期样式如何解决
核心原因
- 第一,
userEvent.hover是异步方法,你当前的代码没有加await,事件还没完成触发就执行了后续断言逻辑。 - 第二,也是最关键的:jsdom(RTL底层依赖的DOM模拟环境)不支持CSS伪类样式的自动匹配。你就算正确触发了mouseenter/mouseover事件,jsdom也不会让元素进入
:hover匹配状态,写在CSS:hover选择器下的样式自然不会生效,你拿到的永远是默认样式。 - 第三,你设置了0.2s的过渡效果,就算样式能生效,默认的断言时机也早于过渡完成的时间,拿不到最终样式。
解决方案
根据你的场景可以选任意一种:
方案1:修改业务实现方式,适配单元测试
把hover状态从CSS伪类改为JS控制的类名:
- 组件内监听
mouseenter和mouseleave事件,动态给按钮添加/移除is-hover类 - 把原来写在
&:hover下的样式挪到&.is-hover下 - 修正测试代码,添加await,调整等待逻辑:
it("should expect the button to shift box-shadow on hover", async () => { render(<PrimaryButton aria-label="sign up">Sign Up</PrimaryButton>); const button = screen.getByRole("button", { name: /sign up/i }); // 必须加await等待hover事件触发完成 await userEvent.hover(button); // 等待过渡完成,timeout设为大于过渡时长即可 await waitFor(() => { expect(button).toHaveStyle( "box-shadow: rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px;" ); }, { timeout: 300 }); });
如果不想等待过渡时间,可以在测试全局样式里添加规则禁用过渡,执行效率更高:
* { transition: none !important; animation: none !important; }
方案2:改用端到端测试工具
如果不想修改业务代码,可以用Cypress、Playwright这类在真实浏览器环境运行的测试工具,浏览器原生支持:hover伪类的状态匹配,无需修改业务逻辑即可正常测试。
内容的提问来源于stack exchange,提问作者MShar
相关产品推荐
相关产品推荐

