Material UI v5 TextField组件导致Jest测试失败问题
问题现象
项目从Material UI v4升级至v5版本后,Jest测试渲染TextField组件时抛出兼容性错误。同组件在MUI v4版本下测试可正常运行,浏览器环境中渲染也无异常。
报错信息如下:
Error: Uncaught [TypeError: Cannot read properties of undefined (reading ‘setAttribute’)] at reportException (/home/node_modules/jest-config/node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:66:24) at innerInvokeEventListeners (/home/node_modules/jest-config/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:341:9) at invokeEventListeners (/home/node_modules/jest-config/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3) at HTMLUnknownElementImpl._dispatch (/home/node_modules/jest-config/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9) at HTMLUnknownElementImpl.dispatchEvent (/home/node_modules/jest-config/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17) at HTMLUnknownElement.dispatchEvent (/home/node_modules/jest-config/node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34) at Object.invokeGuardedCallbackDev (/home/node_modules/react-dom/cjs/react-dom.development.js:4210:16) at invokeGuardedCallback (/home/node_modules/react-dom/cjs/react-dom.development.js:4274:31) at reportUncaughtErrorInDEV (/home/node_modules/react-dom/cjs/react-dom.development.js:22737:5) at captureCommitPhaseError (/home/node_modules/react-dom/cjs/react-dom.development.js:27078:5) TypeError: Cannot read properties of undefined (reading ‘setAttribute’) at /home/node_modules/@emotion/react/dist/emotion-react.cjs.dev.js:206:12 console.error The above error occurred in the <EmotionGlobal> component: at /home/node_modules/@emotion/react/dist/emotion-element-e89f38a3.cjs.dev.js:64:23 at GlobalStyles (/home/node_modules/@mui/styled-engine/node/GlobalStyles/GlobalStyles.js:28:5) at GlobalStyles at InputBase (/home/node_modules/@mui/material/node/InputBase/InputBase.js:251:44) at OutlinedInput (/home/node_modules/@mui/material/node/OutlinedInput/OutlinedInput.js:135:44) at div at /home/node_modules/@emotion/react/dist/emotion-element-e89f38a3.cjs.dev.js:64:23 at FormControl (/home/node_modules/@mui/material/node/FormControl/FormControl.js:111:44) at /home/node_modules/@emotion/react/dist/emotion-element-e89f38a3.cjs.dev.js:64:23 at TextField (/home/node_modules/@mui/material/node/TextField/TextField.js:107:44) at div at /home/node_modules/@emotion/react/dist/emotion-element-e89f38a3.cjs.dev.js:64:23 at Box (/home/node_modules/@mui/system/createBox.js:41:41) at div at /home/node_modules/@emotion/react/dist/emotion-element-e89f38a3.cjs.dev.js:64:23 at Box (/home/node_modules/@mui/system/createBox.js:41:41) at form at CreateNewCVForm (/home/src/project/sciencv/static/sciencv/js/index/CreateNewCVForm.js:16:41) at div at /home/node_modules/@emotion/react/dist/emotion-element-e89f38a3.cjs.dev.js:64:23 at Box (/home/node_modules/@mui/system/createBox.js:41:41) at div at /home/node_modules/@emotion/react/dist/emotion-element-e89f38a3.cjs.dev.js:64:23 at CVListPage (/home/src/project/sciencv/static/sciencv/js/CVListPage.js:77:
已尝试操作
- 已将测试相关依赖全部升级至最新版本
- 已尝试传入组件所有必填、非必填属性,问题仍未解决
当前package.json中开发依赖配置如下:
"devDependencies": { "@babel/core": "^7.16.0", "@babel/plugin-proposal-class-properties": "^7.16.0", "@babel/plugin-proposal-optional-chaining": "^7.16.0", "@babel/plugin-proposal-private-methods": "^7.16.0", "@babel/plugin-transform-react-jsx": "^7.16.0", "@babel/plugin-transform-react-jsx-self": "^7.16.0", "@babel/preset-env": "^7.16.4", "@babel/preset-react": "^7.16.0", "@emotion/react": "^11.9.0", "@emotion/styled": "^11.8.1", "@material-ui/core": "^4.12.4", "@mui/icons-material": "^5.8.3", "@mui/lab": "^5.0.0-alpha.83", "@mui/material": "^5.8.1", "@mui/styles": "^5.8.0", "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.3.0", "axios": "^0.21.4", "babel-eslint": "^10.1.0", "babel-loader": "^8.2.3", "clean-webpack-plugin": "^2.0.1", "clone": "^2.1", "css-loader": "^2.1.1", "cssnano": "^4.1.10", "date-fns": "^2.28.0", "eslint": "^6.8.0", "eslint-config-prettier": "^6.15.0", "eslint-config-standard": "^14.1.1", "eslint-loader": "^3.0.4", "eslint-plugin-import": "^2.25.3", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^4.3.1", "eslint-plugin-standard": "^4.1.0", "file-loader": "^4.2.0", "jest": "^27.3.1", "jest-teamcity-reporter": "^0.9.0", "loglevel": "^1.7.1", "marked": "^1.2.9", "mini-css-extract-plugin": "^0.5.0", "optimize-css-assets-webpack-plugin": "^5.0.1", "prettier": "^2.4.1", "react": "^18.1.0", "react-dom": "^18.1.0", "react-test-renderer": "^18.1.0", "reactstrap": "^8.10.1", "regenerator-runtime": "^0.13.9", "resolve-url-loader": "^3.1.2", "sass": "^1.43.4", "terser-webpack-plugin": "^1.4.3", "url-loader": "^3.0.0", "webpack": "^4.46.0", "webpack-bundle-tracker": "^0.4.3", "webpack-cli": "^3.3.11", "webpack-merge": "^4.2.1" }
修复方案
按以下优先级依次排查处理:
- 修正Jest测试环境配置
Jest 27及以上版本默认测试环境为node,不提供DOM API,渲染React组件必须切换为jsdom环境。在Jest配置文件中添加:
module.exports = { testEnvironment: 'jsdom', // 保留原有其他配置 }
如果本地未安装jsdom依赖,先执行安装:
npm install --save-dev jest-environment-jsdom
- 配置测试初始化逻辑
MUI v5默认使用Emotion作为样式引擎,Emotion注入全局样式时需要依赖DOM的head节点。在Jest的setup文件(通常为setupTests.js)中添加如下初始化逻辑:
import '@testing-library/jest-dom'; beforeAll(() => { // 提前创建head、body节点,避免Emotion注入样式时找不到挂载点 if (!document.head) { const head = document.createElement('head'); document.documentElement.appendChild(head); } if (!document.body) { const body = document.createElement('body'); document.documentElement.appendChild(body); } });
同时确认Jest配置中已正确引入该setup文件:
module.exports = { setupFilesAfterEnv: ['<rootDir>/setupTests.js'], // 其他配置 }
- 清理版本冲突依赖
当前依赖中同时存在v4版本的@material-ui/core和v5版本的@mui/*系列包,两个大版本的样式引擎逻辑存在差异,共存时可能导致实例加载冲突。确认业务代码已全量迁移到v5版本后,卸载v4版本的MUI包:
npm uninstall @material-ui/core
如果需要暂时保留v4版本做过渡迁移,需要在Jest配置中为两个版本的包分别指定模块解析规则,避免样式引擎重复加载。
- 升级jsdom版本
如果上述配置完成后仍报错,检查本地jsdom版本,低于16.0的版本对现代DOM API支持不全,升级到最新稳定版即可。
内容的提问来源于stack exchange,提问作者mc3rvantes
相关产品推荐
相关产品推荐

