使用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
相关产品推荐
相关产品推荐

