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

使用react-test-renderer+TypeScript测试MUI Menu组件报错的解决方法

解决Material-UI Menu组件快照测试的TypeError问题

我之前也碰到过一模一样的问题,用react-test-renderer给Material-UI的Menu组件写快照测试时,总会因为DOM模拟的问题抛出错误,咱们一步步来解决:

原组件代码(Menu.tsx)

import React, { useState } from 'react';
import { Grid, Button, Menu, MenuItem } from '@material-ui/core';

const Component = () => {
  const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
  
  const handleMenuClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    setAnchorEl(event.currentTarget);
  };
  
  const handleMenuClose = () => {
    setAnchorEl(null);
  };
  
  return (
    <Grid>
      <Button variant="contained" onClick={handleMenuClick}>
        Open Menu
      </Button>
      <Menu 
        anchorEl={anchorEl} 
        keepMounted 
        open={Boolean(anchorEl)} 
        onClose={handleMenuClose}
      >
        <MenuItem>Option 1</MenuItem>
        <MenuItem>Option 2</MenuItem>
      </Menu>
    </Grid>
  );
};

export default Component;

原测试代码(Menu.test.tsx)

import React from 'react';
import { create } from 'react-test-renderer';
import Menu from './Menu';

describe('Menu Snapshot', () => {
  it('renders correctly', () => {
    const tree = create(<Menu />).toJSON();
    expect(tree).toMatchSnapshot();
  });
});

问题分析

运行测试时出现的TypeError: parentInstance.children.indexOf is not a function,本质是Material-UI的Menu组件依赖真实DOM元素计算位置,但react-test-renderer默认的无DOM环境没法提供完整的节点模拟。你之前尝试的createNodeMock写法不对,直接返回element并不是符合要求的DOM节点模拟对象。

正确的测试方案

我们需要在createNodeMock里返回一个包含组件必要属性/方法的模拟DOM对象,修改后的测试代码如下:

import React from 'react';
import { create } from 'react-test-renderer';
import Menu from './Menu';

describe('Menu Snapshot', () => {
  it('renders correctly', () => {
    const tree = create(<Menu />, {
      createNodeMock: () => {
        // 模拟Menu组件运行时需要的DOM元素属性与方法
        return {
          getBoundingClientRect: () => ({
            top: 0,
            left: 0,
            bottom: 0,
            right: 0,
            width: 0,
            height: 0
          }),
          addEventListener: () => {},
          removeEventListener: () => {},
          // 可根据组件实际需求补充其他属性
        };
      },
    }).toJSON();
    expect(tree).toMatchSnapshot();
  });
});

补充说明

  • createNodeMock的作用是为React元素生成模拟DOM节点,这里我们只需要提供Menu组件运行时用到的方法(比如计算位置的getBoundingClientRect、事件监听方法),不需要完全复刻真实DOM的所有属性。
  • 这样修改后,测试就能正常执行并生成正确的组件快照了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 19:03:14