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

React测试中Mock渲染Headless UI组件及解决组件渲染为undefined问题

如何在React测试中正确Mock Headless UI组件以解决渲染undefined的问题

看起来你遇到的核心问题是Headless UI的复合组件(比如Menu和Transition)在测试环境中没有被正确Mock,导致渲染时出现undefined。另外你的测试代码中注释了Redux Provider,这可能也会间接导致依赖Redux的子组件(比如AdvertSwitch)无法正常初始化。下面是一步步的解决方案:

1. 修正Headless UI的Mock结构

你当前的Mock只是简单地spread了真实模块,但Headless UI的组件(比如Menu)是包含子组件(Button、Items、Item)的复合对象,在测试环境下直接引用真实模块可能无法正确初始化这些子组件。需要显式模拟这些复合组件的结构:

jest.mock('@headlessui/react', () => {
  // 保留真实模块的其他导出(如果需要)
  const actual = jest.requireActual('@headlessui/react');
  
  return {
    ...actual,
    // 模拟Menu复合组件,返回简单的HTML元素作为替代
    Menu: {
      Button: ({ children, ...props }) => <button {...props}>{children}</button>,
      Items: ({ children, ...props }) => <div {...props}>{children}</div>,
      Item: ({ children, ...props }) => <div {...props}>{children}</div>,
    },
    // 模拟Transition组件,直接返回子元素(假设测试时不需要动画逻辑)
    Transition: ({ children }) => {
      // Transition组件会传递一个包含`open`状态的对象给子元素,这里模拟open为true
      return children({ open: true, close: jest.fn() });
    },
  };
});

这样Mock后,AdvertSwitch中的Menu.Button、Menu.Items等就不会是undefined了,而是被替换成了简单的可渲染元素。

2. 恢复Redux Provider的注入

你的测试代码中注释了<Provider store={store}>,如果App或其子组件(比如Dashboard、AdvertSwitch)依赖Redux状态,那么缺少Store会导致组件无法正常渲染,间接引发子组件undefined的问题。请恢复Store的创建和Provider的包裹:

import { rootReducer } from './store';

function renderApp(
  store = createStore(
    rootReducer,
    {},
    composeWithDevTools(applyMiddleware(thunk))
  ),
  props = {}
) {
  return render(
    <SnackbarProvider>
      <MemoryRouter>
        <Provider store={store}>
          <App {...props} />
        </Provider>
      </MemoryRouter>
    </SnackbarProvider>
  );
}

如果不需要完整的DevTools,也可以简化Store创建:

store = createStore(rootReducer, {}, applyMiddleware(thunk))

3. 验证Mock是否生效

在AdvertSwitch中你已经加了console.log({ Menu, Transition }),运行测试时查看控制台输出:

  • 如果输出的是你Mock的组件结构(比如Menu.Button是一个函数组件),说明Mock成功;
  • 如果还是undefined,检查Mock的路径是否正确(比如@headlessui/react是否是正确的包名),或者是否有其他地方覆盖了这个Mock。

4. 优化测试断言

最后,为了确保测试有效,建议添加一些断言,比如检查AdvertSwitch中的广告商名称是否被渲染:

test('test render app component with AdvertSwitch', async () => {
  const { getByText } = renderApp();
  // 检查第一个广告商名称是否存在
  expect(getByText('advertiser-one')).toBeInTheDocument();
});

这样可以明确验证组件是否正确渲染,而不仅仅是没有报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 17:28:13