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 版本或模块,这可能会导致问题。

遇到同样的问题,按照步骤解决,

  1. 安装 babel-jest
  2. 在 jest 配置中添加此配置
       transform: {
           '^.+\.js?$': require.resolve('babel-jest')
       }
  1. 确保你有 babel.config.js 存在(你的配置可能与下面提供的不同)
    module.exports = {
      "env": {
        "test": {
          presets: [
            [
              '@babel/preset-env',
              {
                targets: {
                  node: 'current',
                },
              },
            ],
          ]
        }
      }
    };