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

React Testing Library无法检测MUI样式组件的:hover样式

测试MUI样式组件hover样式的正确方法

问题场景

在Next.js 13+ App Router项目中,使用Jest和React Testing Library测试MUI styled 生成的按钮组件时,hover状态的样式断言失败,但该效果在浏览器中正常工作。手动通过onMouseEnter/onMouseLeave绑定内联样式时,测试可以通过。

组件代码(TestButton.tsx)

import { styled } from "@mui/material/styles";
import type { FC } from "react";

const MyButton = styled("button")({
  color: "red",
  "&:hover": {
    color: "yellow",
  },
});

const TestButton: FC = () => {
  return <MyButton className="button">Test Button</MyButton>;
};

export default TestButton;

测试代码(TestButton.spec.tsx)

import TestButton from "~/components/testButton/TestButton";
import { Renderer } from "./Renderer";
import { act } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

describe("TestButton", () => {
  it("should change text color on hover", async () => {
    const user = userEvent.setup();
    const { getByRole } = await act(() => new Renderer(<TestButton />).withAllProviders().render());

    const button = getByRole("button", { name: /Test Button/i });

    expect(button).toHaveStyle({
      color: "red",
    });

    await act(async () => {
      await user.hover(button);
    });

    expect(button).toHaveStyle({
      color: "yellow", // ❌ 测试失败
    });

    await act(async () => {
      await user.unhover(button);
    });

    expect(button).toHaveStyle("color: red");
  });
});

测试失败输出

FAIL  src/__test__/TestButton.spec.tsx
TestButton
  × should change text color on hover (168 ms)

  ● TestButton › should change text color on hover

    expect(element).toHaveStyle()

    - Expected

    - color: yellow;
    + color: red;

问题原因

Jest依赖的jsdom环境对CSS伪类(如:hover)的样式计算支持有限,toHaveStyle断言仅检查元素的内联样式或jsdom计算出的当前样式,无法正确识别MUI styled 生成的伪类样式规则。而手动绑定onMouseEnter/onMouseLeave时,样式是直接设置到元素的内联style属性,因此能被toHaveStyle捕获。

解决方案

推荐使用@emotion/jest提供的toHaveStyleRule匹配器,它可以直接解析MUI(基于Emotion)生成的样式规则,包括伪类状态下的样式。

步骤1:安装依赖

npm install --save-dev @emotion/jest

步骤2:配置Jest(可选)

若要全局启用该匹配器,在jest.config.js中添加:

module.exports = {
  setupFilesAfterEnv: ["@emotion/jest"],
};

或者在单个测试文件顶部导入:

import '@emotion/jest';

步骤3:修改测试代码

将原来的toHaveStyle断言替换为toHaveStyleRule,并通过modifier指定伪类:

import TestButton from "~/components/testButton/TestButton";
import { Renderer } from "./Renderer";
import { act } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import '@emotion/jest'; // 若未全局配置则添加此行

describe("TestButton", () => {
  it("should change text color on hover", async () => {
    const user = userEvent.setup();
    const { getByRole } = await act(() => new Renderer(<TestButton />).withAllProviders().render());

    const button = getByRole("button", { name: /Test Button/i });

    // 检查初始样式
    expect(button).toHaveStyleRule('color', 'red');

    // 触发hover并检查伪类样式
    await user.hover(button);
    expect(button).toHaveStyleRule('color', 'yellow', { modifier: ':hover' });

    // 离开hover并恢复检查
    await user.unhover(button);
    expect(button).toHaveStyleRule('color', 'red');
  });
});

原理说明

toHaveStyleRule会直接从Emotion生成的样式表中查找目标元素对应的样式规则,包括伪类、媒体查询等特殊规则,无需依赖jsdom对这些状态的计算支持,因此能准确验证MUI styled组件的样式逻辑。

内容的提问来源于stack exchange,提问作者Haitam-Elgharras

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 10:25:23