babel-jest 不处理模块内的 ES6
babel-jest doesn't handle ES6 within modules
我正在尝试在使用 ES6 模块的基于 React 的项目上设置 Jest。但是我似乎遇到了 ES6 模块的问题,我正在使用 babel-jest 并且相信我已经正确设置了它(Jest 会自动检测到它)。
Jest 使用 ES6 导入似乎没有问题,但是一旦它在其中一个导入模块中遇到导入语句,它就会阻塞。就好像它只是在转译初始测试脚本而不是任何导入的模块。我尝试了各种配置并尝试搜索 Google 但没有成功。 运行 没有任何导入的测试工作正常。
这里是错误:
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import Predications from './predications';
^^^^^^
SyntaxError: Unexpected token import
以下是配置的相关位:
jest.conf.json
{
"testRegex": "\/test\/spec\/.*\.js$",
}
.babelrc
{
"presets": ["es2015", "stage-0", "react"]
}
测试脚本
import React from 'react';
import { mount, shallow } from 'enzyme';
import Slider from 'react-slick';
import Carousel from '../../client/components/carousel/carousel.js'; // test chokes on when I include this module
describe('carousel component', () => {
it('is a test test case', () => {
expect(1 + 2).toEqual(3);
});
});
更新:
按照建议,我尝试了 运行 没有 jest.conf.js 的测试,但是为了让 Jest 找到我的测试,需要 testRegex,我尝试将测试移动到默认测试目录,它们仍然失败。
我想澄清一下,测试本身 运行 没问题,问题似乎出在我导入的模块之一使用 ES6 的地方,在我上面的示例中,如果我不导入我的轮播组件测试运行良好,只要我导入该文件中的导入语句,测试就会阻塞。似乎导入的模块没有被转译。
更新 #2
经过一些调查,问题似乎是 babel 没有在 node_modules 中转译 ES6。我在这里创建了一个示例回购来证明这一点:https://github.com/jamiedust/babel-jest-example
我知道第三方模块应该处理他们自己的转译,但是我们有许多模块托管在我们自己的 npm 注册表中,并在项目之间重复使用,在这些情况下,Webpack 处理转译,用于Jest 测试我们需要这些 node_modules 由 Babel 转译,或者利用我们的 webpack 设置为我们做这件事的方法。
解决方案
在 package.json(或 Jest 配置文件)中添加以下配置。
"jest": {
"transformIgnorePatterns": [
"/node_modules/(?!test-component).+\.js$"
]
}
您可以尝试将 transform-es2015-modules-commonjs 插件添加到您的 babel 配置文件中,仅用于测试。这是一个示例配置文件,它告诉 babel 仅在测试环境中转译模块。你可以把它放在你的预设下面:
{
"presets": [
"react",
["es2015", {"modules": false, "loose": true}]
],
"env": {
"test": {
"plugins": ["transform-es2015-modules-commonjs"]
}
}
}
您可以在此处阅读有关该插件的信息:
https://www.npmjs.com/package/babel-plugin-transform-es2015-modules-commonjs
然后,当 运行 你的 Jest 在命令行上测试时指定 NODE_ENV=test (你可能需要在第一次添加 --no-cache 标志到命令后更改 babel 配置,因为 Jest 缓存 babel 输出,但之后你可以将其关闭:
NODE_ENV=test jest --no-cache
我是在 Frontend Masters 的 Brian Holt 举办的 React 研讨会上了解到这个问题的。 https://frontendmasters.com/courses/
我遇到了同样的问题(node_module 没有被 babel-jest 转译),但无法解决。
相反,我最终通过模拟 node_module 取得了成功,如此处所述 https://facebook.github.io/jest/docs/manual-mocks.html
注意:在 __mocks__
子文件夹中设置模拟对我不起作用。所以我将模拟作为 jest.mock()
函数的第二个参数传递。像 :
jest.mock('your_node_module', () => {})
默认情况下,node_modules
中的任何代码都会被 babel-jest
忽略,请参阅 Jest 配置选项 transformIgnorePatterns
. I've also created a PR on your example repo,因此您可以看到它正在运行。
虽然这可行,但我发现它在具有大量包含 ES 模块的依赖项的实际应用程序中非常慢。您可以在 babel-jest transforming dependencies. This can also take much longer on Windows, see Taking 10 seconds on an empty repo.
中找到 Jest 代码库对此的方法略有不同
如果进行“单元”测试,模拟可能是更好的方法。
另一个可能的原因。 Babel 现在忽略 node_modules 中的 .babelrc 并使用依赖项提供的那个。如果您可以控制依赖项,则必须向其添加 .babelrc 并且 babel 将为它使用这些设置。
如果您的依赖项和项目使用不同的 babel 版本或模块,这可能会导致问题。
遇到同样的问题,按照步骤解决,
- 安装 babel-jest
- 在 jest 配置中添加此配置
transform: {
'^.+\.js?$': require.resolve('babel-jest')
}
- 确保你有 babel.config.js 存在(你的配置可能与下面提供的不同)
module.exports = {
"env": {
"test": {
presets: [
[
'@babel/preset-env',
{
targets: {
node: 'current',
},
},
],
]
}
}
};
我正在尝试在使用 ES6 模块的基于 React 的项目上设置 Jest。但是我似乎遇到了 ES6 模块的问题,我正在使用 babel-jest 并且相信我已经正确设置了它(Jest 会自动检测到它)。
Jest 使用 ES6 导入似乎没有问题,但是一旦它在其中一个导入模块中遇到导入语句,它就会阻塞。就好像它只是在转译初始测试脚本而不是任何导入的模块。我尝试了各种配置并尝试搜索 Google 但没有成功。 运行 没有任何导入的测试工作正常。
这里是错误:
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import Predications from './predications';
^^^^^^
SyntaxError: Unexpected token import
以下是配置的相关位:
jest.conf.json
{
"testRegex": "\/test\/spec\/.*\.js$",
}
.babelrc
{
"presets": ["es2015", "stage-0", "react"]
}
测试脚本
import React from 'react';
import { mount, shallow } from 'enzyme';
import Slider from 'react-slick';
import Carousel from '../../client/components/carousel/carousel.js'; // test chokes on when I include this module
describe('carousel component', () => {
it('is a test test case', () => {
expect(1 + 2).toEqual(3);
});
});
更新:
按照建议,我尝试了 运行 没有 jest.conf.js 的测试,但是为了让 Jest 找到我的测试,需要 testRegex,我尝试将测试移动到默认测试目录,它们仍然失败。
我想澄清一下,测试本身 运行 没问题,问题似乎出在我导入的模块之一使用 ES6 的地方,在我上面的示例中,如果我不导入我的轮播组件测试运行良好,只要我导入该文件中的导入语句,测试就会阻塞。似乎导入的模块没有被转译。
更新 #2
经过一些调查,问题似乎是 babel 没有在 node_modules 中转译 ES6。我在这里创建了一个示例回购来证明这一点:https://github.com/jamiedust/babel-jest-example
我知道第三方模块应该处理他们自己的转译,但是我们有许多模块托管在我们自己的 npm 注册表中,并在项目之间重复使用,在这些情况下,Webpack 处理转译,用于Jest 测试我们需要这些 node_modules 由 Babel 转译,或者利用我们的 webpack 设置为我们做这件事的方法。
解决方案
在 package.json(或 Jest 配置文件)中添加以下配置。
"jest": {
"transformIgnorePatterns": [
"/node_modules/(?!test-component).+\.js$"
]
}
您可以尝试将 transform-es2015-modules-commonjs 插件添加到您的 babel 配置文件中,仅用于测试。这是一个示例配置文件,它告诉 babel 仅在测试环境中转译模块。你可以把它放在你的预设下面:
{
"presets": [
"react",
["es2015", {"modules": false, "loose": true}]
],
"env": {
"test": {
"plugins": ["transform-es2015-modules-commonjs"]
}
}
}
您可以在此处阅读有关该插件的信息:
https://www.npmjs.com/package/babel-plugin-transform-es2015-modules-commonjs
然后,当 运行 你的 Jest 在命令行上测试时指定 NODE_ENV=test (你可能需要在第一次添加 --no-cache 标志到命令后更改 babel 配置,因为 Jest 缓存 babel 输出,但之后你可以将其关闭:
NODE_ENV=test jest --no-cache
我是在 Frontend Masters 的 Brian Holt 举办的 React 研讨会上了解到这个问题的。 https://frontendmasters.com/courses/
我遇到了同样的问题(node_module 没有被 babel-jest 转译),但无法解决。
相反,我最终通过模拟 node_module 取得了成功,如此处所述 https://facebook.github.io/jest/docs/manual-mocks.html
注意:在 __mocks__
子文件夹中设置模拟对我不起作用。所以我将模拟作为 jest.mock()
函数的第二个参数传递。像 :
jest.mock('your_node_module', () => {})
默认情况下,node_modules
中的任何代码都会被 babel-jest
忽略,请参阅 Jest 配置选项 transformIgnorePatterns
. I've also created a PR on your example repo,因此您可以看到它正在运行。
虽然这可行,但我发现它在具有大量包含 ES 模块的依赖项的实际应用程序中非常慢。您可以在 babel-jest transforming dependencies. This can also take much longer on Windows, see Taking 10 seconds on an empty repo.
中找到 Jest 代码库对此的方法略有不同如果进行“单元”测试,模拟可能是更好的方法。
另一个可能的原因。 Babel 现在忽略 node_modules 中的 .babelrc 并使用依赖项提供的那个。如果您可以控制依赖项,则必须向其添加 .babelrc 并且 babel 将为它使用这些设置。
如果您的依赖项和项目使用不同的 babel 版本或模块,这可能会导致问题。
遇到同样的问题,按照步骤解决,
- 安装 babel-jest
- 在 jest 配置中添加此配置
transform: {
'^.+\.js?$': require.resolve('babel-jest')
}
- 确保你有 babel.config.js 存在(你的配置可能与下面提供的不同)
module.exports = {
"env": {
"test": {
presets: [
[
'@babel/preset-env',
{
targets: {
node: 'current',
},
},
],
]
}
}
};