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

使用Jest测试React createRoot渲染,验证MyThemeProvider加载及报错修复

解决React测试中的__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED报错并验证MyThemeProvider加载

问题背景

我在React项目中通过以下代码添加了自定义主题:

//main.tsx
import App from "./app/lib/App";
import { ThemeProvider } from "./core";
import { MyThemeProvider} from "./MyThemeProvider";
import { themeRegistries} from "./ThemeProviders/themeRegistries";

const domNode = document.getElementById("root");
createRoot(domNode).render(
  <ThemeProvider themeName={"CompanyDefaultTheme"}>
    <MyThemeProvider
      applicationName="My Custom Application Name"
      scopeName="My application scope"
      themeName="MyCustomTheme"
      themeRegistries={[themeRegistries]}
    >
       <App />
    </MyThemeProvider>
  </ThemeProvider>
);

我计划通过查找包含My Custom Application Name的元素来验证MyThemeProvider是否成功加载,编写的测试代码如下:

//main.spec.tsx
/// <reference types="jest" />
import React from "react";
import { screen } from "@testing-library/react";

jest.mock("react-dom", () => {
  jest.fn();
});

describe("Application root", () => {
  it("should render without crashing", async () => {
    const div = document.createElement("div");
    div.id = "root";
    document.body.appendChild(div);

    require("./main");
    const component = await screen.findByText("My Custom Application Name");
    expect(component).toBeInTheDocument();
  });
});

报错信息

测试运行后出现如下报错:

● Test suite failed to run

    TypeError: Cannot read properties of undefined (reading '__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED')

      2 | import React from "react";
    > 3 | import { screen } from "@testing-library/react";
        | ^
      4 |
      5 | jest.mock("react-dom", () => {
      6 |   jest.fn();

      at ../../node_modules/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom/cjs/react-dom-test-utils.development.js:1125:32
      at Object.<anonymous> (../../node_modules/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom/cjs/react-dom-test-utils.development.js:1740:5)
      at Object.<anonymous> (../../node_modules/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom/test-utils.js:6:20)
      at Object.<anonymous> (../../node_modules/.pnpm/@testing-library+react@13.4.0_react-dom@18.2.0_react@18.2.0/node_modules/@testing-library/react/dist/act-compat.js:10:41)
      at Object.<anonymous> (../../node_modules/.pnpm/@testing-library+react@13.4.0_react-dom@18.2.0_react@18.2.0/node_modules/@testing-library/react/dist/index.js:7:18)
      at Object.<anonymous> (src/main.spec.tsx:4:1)

解决方案

1. 移除错误的react-dom Mock

你当前的jest.mock("react-dom")写法完全替换了react-dom的导出,导致@testing-library/react依赖的内部方法无法正常访问,直接删除这段mock代码即可。

2. 优化测试逻辑,直接渲染组件

放弃加载整个入口文件的方式,改用@testing-library/react的render方法直接渲染目标组件结构,这样测试更可控,也符合测试最佳实践:

修改后的测试代码:

//main.spec.tsx
/// <reference types="jest" />
import React from "react";
import { render, screen } from "@testing-library/react";
import App from "./app/lib/App";
import { ThemeProvider } from "./core";
import { MyThemeProvider} from "./MyThemeProvider";
import { themeRegistries} from "./ThemeProviders/themeRegistries";

describe("Application root", () => {
  it("should render MyThemeProvider with correct application name", async () => {
    // 直接渲染需要测试的组件层级
    render(
      <ThemeProvider themeName={"CompanyDefaultTheme"}>
        <MyThemeProvider
          applicationName="My Custom Application Name"
          scopeName="My application scope"
          themeName="MyCustomTheme"
          themeRegistries={[themeRegistries]}
        >
          <App />
        </MyThemeProvider>
      </ThemeProvider>
    );

    // 查找目标文本并断言存在
    const appNameElement = await screen.findByText("My Custom Application Name");
    expect(appNameElement).toBeInTheDocument();
  });
});

3. 额外验证:检查主题上下文(可选)

如果MyThemeProvider是通过React上下文传递主题数据,还可以直接验证上下文值来确认它的工作状态:

// 假设MyThemeProvider导出了对应的Context对象
import { MyThemeContext } from "./MyThemeProvider";

it("should provide correct theme context values", () => {
  let contextValue;
  render(
    <ThemeProvider themeName={"CompanyDefaultTheme"}>
      <MyThemeProvider
        applicationName="My Custom Application Name"
        scopeName="My application scope"
        themeName="MyCustomTheme"
        themeRegistries={[themeRegistries]}
      >
        <MyThemeContext.Consumer>
          {(value) => {
            contextValue = value;
            return null;
          }}
        </MyThemeContext.Consumer>
        <App />
      </MyThemeProvider>
    </ThemeProvider>
  );

  expect(contextValue.applicationName).toBe("My Custom Application Name");
  expect(contextValue.themeName).toBe("MyCustomTheme");
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 12:51:03