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

material-ui菜单实际运行正常 点击关闭后测试断言菜单消失失败

问题原因

Material UI 内置的 Menu 组件底层基于 Popover 实现,默认带有关闭过渡动画。你点击菜单项触发关闭逻辑后,测试会立即执行断言,此时过渡动画还未执行完成,Menu 的根 DOM 节点尚未被卸载,因此 queryByTestId("lang-menu") 仍然能查询到元素,导致 toBeNull() 断言失败。
浏览器中运行正常是因为普通用户感知不到几十毫秒的过渡延迟,不会有异常感知。

解决方案

推荐三种可行方案,按需选择即可:

方案1:等待元素完全卸载(最符合真实场景)

使用 @testing-library/react 提供的 waitForElementToBeRemoved 工具方法,主动等待 Menu 元素被完全移除后再执行后续校验,测试用例需要改成异步写法:

import { render, screen, waitForElementToBeRemoved } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import React from "react";

import LanguageMenu from "../LanguageMenu";

describe("<LanguageMenu />", () => {
  // 测试用例加async标识
  it("renders menu correctly when opened and closed", async () => {
    render(<LanguageMenu />);
    expect(screen.queryByTestId("lang-menu")).toBeNull();

    userEvent.click(screen.getByRole("button"));
    expect(screen.getByTestId("lang-menu")).toMatchSnapshot();
    expect(screen.getByTestId("lang-menu")).toBeVisible();

    userEvent.click(screen.getByText("Menu Button"));
    // 等待元素完全卸载,该方法本身会做校验,不需要额外写toBeNull断言
    await waitForElementToBeRemoved(screen.getByTestId("lang-menu"));
  });
});

方案2:禁用Menu组件的过渡动画

如果不需要测试过渡效果,可以直接给Menu组件关闭过渡,关闭后元素会在触发关闭逻辑时立即卸载,同步断言即可生效:

// 组件代码中修改Menu属性
<Menu
  data-testid="lang-menu"
  id="test-menu"
  anchorEl={anchorEl}
  open={Boolean(anchorEl)}
  onClick={handleClose}
  onClose={handleClose}
  // 新增属性禁用过渡
  TransitionComponent={props => <>{props.children}</>}
>
  <MenuItem key="item1" onClick={handleClose}>
    Menu Button
  </MenuItem>
</Menu>

方案3:使用keepMounted属性时的适配

如果你保留了keepMounted属性(菜单不会卸载,只会隐藏),不需要断言toBeNull,等待过渡完成后断言不可见即可:

// 测试用例修改最后一段断言
userEvent.click(screen.getByText("Menu Button"));
// 等待过渡完成,断言不可见
await waitFor(() => {
  expect(screen.getByTestId("lang-menu")).not.toBeVisible();
})

内容的提问来源于stack exchange,提问作者Cielquan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 07:36:03