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

从index.js导入router致Jest/RTL测试出现DOM元素错误

问题原因及解决方法

问题原因

  • 只要你从index.js导入任何变量(包括router),整个index.js的代码都会被执行,包括末尾那段ReactDOM.createRoot(...).render(...)的应用渲染逻辑。
  • 测试环境(Jest/React Testing Library)运行时,测试页面里不存在id="root"的DOM元素,document.getElementById('root')会返回null,调用createRoot(null)自然就抛出Target container is not a DOM element错误。
  • 哪怕你导入后根本没用到这个变量,只要触发了index.js的代码执行,就会触发这个错误。

解决方法

方案一:把路由配置单独抽成文件(推荐)

这是最干净的解决方案,彻底分离路由配置和应用渲染逻辑:

  1. 新建src/router.js文件,把路由配置移进去:
import React from "react";
import { createBrowserRouter } from "react-router-dom";
import App from "./App";
import ErrorPage from "./components/ErrorPage/ErrorPage";

export const router = createBrowserRouter([
  {
    path: "/",
    element: <App />,
    errorElement: <ErrorPage />,
  },
]);
  1. 修改src/index.js,从新文件导入router:
import React from "react";
import ReactDOM from "react-dom/client";
import { Provider } from "react-redux";
import { RouterProvider } from "react-router-dom";
import "./index.css";
import store from "./store";
import { router } from "./router"; // 从单独文件导入路由配置

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <RouterProvider router={router} />
    </Provider>
  </React.StrictMode>
);
  1. 在测试文件(setupTests.js或App.test.js)中,从router.js导入router:
import { router } from "../router"; // 不再导入index.js,避免触发渲染逻辑

这样导入路由配置时,只会加载路由相关代码,不会执行应用渲染,测试环境就不会报错。

方案二:给index.js加环境判断

如果不想抽离文件,可以在index.js里判断当前环境,只在浏览器环境执行渲染:

修改src/index.js的末尾代码:

export const router = createBrowserRouter([
  {
    path: "/",
    element: <App />,
    errorElement: <ErrorPage />,
  },
]);

// 只在浏览器环境执行渲染(测试环境中window对象不存在)
if (typeof window !== 'undefined') {
  const root = ReactDOM.createRoot(document.getElementById('root'));
  root.render(
    <React.StrictMode>
      <Provider store={store}>
        <RouterProvider router={router} />
      </Provider>
    </React.StrictMode>
  );
}

测试环境中typeof window会返回undefined,渲染代码不会执行,也就不会出现找不到DOM元素的问题。

补充:测试错误页面的正确姿势

用抽离后的路由配置,你可以直接用createMemoryRouter来模拟错误路径的场景:

test('An invalid path returns an error page', () => {
  import { createMemoryRouter, RouterProvider } from 'react-router-dom';
  import ErrorPage from './components/ErrorPage/ErrorPage';
  
  // 创建测试用的内存路由
  const testRouter = createMemoryRouter([
    {
      path: "/",
      element: <App />,
      errorElement: <ErrorPage />,
    },
  ], {
    initialEntries: ["/invalid-path"] // 模拟访问无效路径
  });

  // 直接渲染RouterProvider,不需要MemoryRouter
  renderWithProviders(<RouterProvider router={testRouter} />, { useRouter: false });
  expect(screen.getByText("Sorry, an unexpected error has occurred!")).toBeInTheDocument();
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 19:15:56