Babel 6升级至7后Mocha+Enzyme单元测试报错求助
我升级Babel 7的时候刚好碰到过几乎一模一样的问题,当时折腾了好一阵才找到根源——本质是Babel 7对模块转译、解析的逻辑和v6有不少差异,尤其是你用索引文件统一导出组件的场景,很容易因为配置不到位导致测试环境下导入的组件不是预期的函数形式,进而触发reselect的错误。下面是几个最可能的原因和对应的解决办法:
1. 测试环境未正确转译ES模块为CommonJS
Mocha默认使用CommonJS模块系统,而Babel 7的@babel/preset-env默认在测试环境下可能不会自动把ES模块转成CommonJS。当你通过索引文件导入组件时,未转译的模块导出可能导致reselect接收到非函数的输入。
解决办法:
在你的Babel配置文件(.babelrc或babel.config.js)的test环境中,明确设置@babel/preset-env的modules选项为commonjs,或者直接启用@babel/plugin-transform-modules-commonjs插件。
示例配置(.babelrc):
{ "env": { "test": { "presets": [ ["@babel/preset-env", { "modules": "commonjs" }], "@babel/preset-react" ], "plugins": ["@babel/plugin-transform-modules-commonjs"] } } }
2. 缺少模块别名解析插件或配置错误
你用import { ABC } from 'componentIndex';这种别名导入方式,Babel 7需要明确的模块解析规则来识别这个别名对应的实际文件路径。如果没有配置babel-plugin-module-resolver或者配置有误,测试环境下无法正确解析索引文件,就会导致导入的组件异常。
解决办法:
首先安装插件:
npm install babel-plugin-module-resolver --save-dev
然后在Babel配置中添加别名映射:
{ "plugins": [ ["module-resolver", { "alias": { "componentIndex": "./src/components/index" // 替换成你的组件索引文件实际路径 } }] ] }
另外要确保Mocha能识别这个别名,你可以在Mocha配置文件(.mocharc.js)中指定用@babel/register来处理模块解析:
module.exports = { require: ['@babel/register'] };
3. Enzyme适配Babel 7的插件缺失
Enzyme在Babel 7环境下需要额外的语法转译支持,比如你的组件如果用到了类属性、对象扩展运算符等ES6+语法,而测试环境没有启用对应的Babel插件,就会导致组件导出的结构异常。
解决办法:
安装必要的插件:
npm install @babel/plugin-proposal-class-properties @babel/plugin-proposal-object-rest-spread --save-dev
然后把它们添加到Babel的test环境配置中:
{ "env": { "test": { "plugins": [ "@babel/plugin-proposal-class-properties", "@babel/plugin-proposal-object-rest-spread" ] } } }
同时确保你用了适配React版本的Enzyme适配器,比如React 16对应enzyme-adapter-react-16,并在测试文件开头配置:
import Enzyme from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; Enzyme.configure({ adapter: new Adapter() });
4. 索引文件的导出方式存在兼容性问题
Babel 7对命名导出的转译逻辑和v6略有不同,比如如果你的组件是默认导出,但你在索引文件里用export { ABC }来导出(而不是export { default as ABC } from './path'),就可能导致导出的内容不是预期的组件函数。
解决办法:
检查你的组件索引文件,确保导出方式正确:
- 如果组件是默认导出:
// 组件文件ABC.js export default ABC; // 索引文件index.js import ABC from './common/Folder/ABC'; export { ABC }; // 或者更明确的 export { default as ABC } from './common/Folder/ABC'; - 确保没有混合默认导出和命名导出导致的混淆,尽量保持导出方式一致。
内容的提问来源于stack exchange,提问作者Rain.To

