运行Jest时遭遇React DND错误:Jest encountered an unexpected token
解决React 18 + React DnD 16下Jest运行报错问题
依赖版本
- react: 18.1.0
- react-dnd: 16.0.1
当前Jest配置
process.env.TZ = 'UTC' const nxPreset = require('@nrwl/jest/preset') module.exports = { ...nxPreset, moduleNameMapper: { '^antd/es/(.*)$': `${__dirname}/node_modules/antd/lib/$1` }, transform: { '\\.svg$': `${__dirname}/tools/tests/svgrTransformer.js`, '\\.(png|jpg|jpeg|webp)$': `${__dirname}/tools/tests/imagerTransformer.js` }, coverageReporters: [ 'lcov', 'text-summary' ], collectCoverageFrom: [ '<rootDir>/src/**/*.{js,jsx,ts,tsx}', ... ], setupFilesAfterEnv: [`${__dirname}/jest.setup.js`, 'jest-canvas-mock'] }
解决方案
结合React 18和React DnD 16的特性,以及Jest的运行机制,以下是针对性修复步骤:
1. 模拟React DnD核心API
React DnD依赖真实DOM拖拽事件,测试环境无法提供完整支持,需手动模拟相关API:
- 在项目根目录创建
__mocks__文件夹,添加两个模拟文件:
__mocks__/react-dnd.js:
export const DndProvider = ({ children }) => children; export const useDrag = jest.fn(() => [null, jest.fn(), jest.fn()]); export const useDrop = jest.fn(() => [null, jest.fn(), jest.fn()]); // 按需添加其他React DnD导出API(如DragSource、DropTarget等)
__mocks__/react-dnd-html5-backend.js:
export default {};
- 在Jest配置的
moduleNameMapper中添加映射:
moduleNameMapper: { '^antd/es/(.*)$': `${__dirname}/node_modules/antd/lib/$1`, 'react-dnd': '<rootDir>/__mocks__/react-dnd.js', 'react-dnd-html5-backend': '<rootDir>/__mocks__/react-dnd-html5-backend.js' },
2. 适配React 18的Jest环境
React 18要求测试环境使用jsdom,且Jest 28+需单独安装该依赖:
- 安装依赖:
npm install --save-dev jest-environment-jsdom
- 在Jest配置中指定测试环境:
testEnvironment: 'jsdom',
3. 修复ES模块转换问题
React DnD及其依赖使用ES模块语法,Jest默认不转换node_modules中的文件,需调整transformIgnorePatterns:
transformIgnorePatterns: [ 'node_modules/(?!(react-dnd|dnd-core|@react-dnd|antd|@ant-design))' ],
同时确保React/TypeScript文件能被正确转换,补充transform规则:
transform: { '\\.svg$': `${__dirname}/tools/tests/svgrTransformer.js`, '\\.(png|jpg|jpeg|webp)$': `${__dirname}/tools/tests/imagerTransformer.js`, '^.+\\.(ts|tsx|js|jsx)$': 'babel-jest' },
4. 完整修改后的Jest配置
process.env.TZ = 'UTC' const nxPreset = require('@nrwl/jest/preset') module.exports = { ...nxPreset, moduleNameMapper: { '^antd/es/(.*)$': `${__dirname}/node_modules/antd/lib/$1`, 'react-dnd': '<rootDir>/__mocks__/react-dnd.js', 'react-dnd-html5-backend': '<rootDir>/__mocks__/react-dnd-html5-backend.js' }, transform: { '\\.svg$': `${__dirname}/tools/tests/svgrTransformer.js`, '\\.(png|jpg|jpeg|webp)$': `${__dirname}/tools/tests/imagerTransformer.js`, '^.+\\.(ts|tsx|js|jsx)$': 'babel-jest' }, transformIgnorePatterns: [ 'node_modules/(?!(react-dnd|dnd-core|@react-dnd|antd|@ant-design))' ], coverageReporters: [ 'lcov', 'text-summary' ], collectCoverageFrom: [ '<rootDir>/src/**/*.{js,jsx,ts,tsx}', // 补充完整需收集覆盖率的文件路径 ], setupFilesAfterEnv: [`${__dirname}/jest.setup.js`, 'jest-canvas-mock'], testEnvironment: 'jsdom' }
5. 补充Jest初始化配置(可选)
若使用@testing-library/react,在jest.setup.js中添加:
import '@testing-library/jest-dom'; // 开启React 18并发测试支持 globalThis.IS_REACT_ACT_ENVIRONMENT = true;
内容的提问来源于stack exchange,提问作者Suraj Bande
相关产品推荐
相关产品推荐

