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

如何测试React.createPortal渲染的组件?Jest+RTL测试报错

解决React Portal组件在Jest+React Testing Library测试中的"Target container is not a DOM element"错误

问题出在你的Popup组件使用React.createPortal时,依赖的目标DOM容器在Jest的jsdom测试环境中不存在。生产环境里你可能在index.html中预先定义了这个容器(比如<div id="modal-root"></div>),但测试环境默认不会包含它,所以渲染时找不到目标元素报错。

以下是两种可行的解决方法:

方法一:测试前后手动创建/移除目标容器

在测试用例执行前后,手动向jsdom的document中添加和移除Portal所需的DOM容器:

import { render, screen } from '@testing-library/react';
import Popup from './Popup';

describe('PopUp', () => {
  let modalRoot;

  beforeEach(() => {
    // 创建目标容器并添加到body,id需和Popup组件中使用的一致
    modalRoot = document.createElement('div');
    modalRoot.setAttribute('id', 'modal-root');
    document.body.appendChild(modalRoot);
  });

  afterEach(() => {
    // 测试结束后移除容器,避免影响其他测试
    document.body.removeChild(modalRoot);
  });

  it("Render PopUp Properly", () => {
    const props = {
      setIsOpen: jest.fn(),
      children: <div>Test</div>,
    };
    render(<Popup isOpen={true} {...props} />);
    expect(screen.getByTestId("popup-component")).toBeInTheDocument();
  });
});

方法二:给Popup组件添加可配置的容器属性

修改Popup组件,允许传入自定义的容器元素,这样测试时可以直接传入一个临时创建的DOM节点:

第一步:修改Popup组件

import { createPortal } from 'react';

const Popup = ({ isOpen, setIsOpen, children, container }) => {
  // 默认使用页面中的modal-root,没有则用传入的容器
  const targetContainer = container || document.getElementById('modal-root');
  
  if (!isOpen) return null;

  return createPortal(
    <motion.div data-testid="popup-component">
      {/* 组件原有内容 */}
      {children}
    </motion.div>,
    targetContainer
  );
};

export default Popup;

第二步:修改测试代码

import { render, screen } from '@testing-library/react';
import Popup from './Popup';

it("Render PopUp Properly", () => {
  const testContainer = document.createElement('div');
  document.body.appendChild(testContainer);

  const props = {
    setIsOpen: jest.fn(),
    children: <div>Test</div>,
    container: testContainer // 传入自定义容器
  };
  
  render(<Popup isOpen={true} {...props} />);
  expect(screen.getByTestId("popup-component")).toBeInTheDocument();

  // 清理临时容器
  document.body.removeChild(testContainer);
});

这两种方法都能解决测试环境中找不到Portal目标容器的问题,你可以根据项目需求选择合适的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 07:10:36