babel-jest 不处理模块内的 ES6

Posted

技术标签:

【中文标题】babel-jest 不处理模块内的 ES6【英文标题】:babel-jest doesn't handle ES6 within modules 【发布时间】:2017-07-02 18:34:05 【问题描述】:

我正在尝试在使用 ES6 模块的基于 React 的项目上设置 Jest。但是我似乎遇到了 ES6 模块的问题,我正在使用 babel-jest 并且相信我已经正确设置了这个(Jest 会自动检测到它)。

Jest 使用 ES6 导入似乎没有问题,但是一旦它在一个导入的模块中遇到 import 语句,它就会窒息。就好像它只是在转换初始测试脚本而不是任何导入的模块。我尝试了各种配置并尝试搜索谷歌但没有运气。在没有任何导入的情况下运行测试工作正常。

这是错误:

("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 的情况下运行测试,但是需要 testRegex 才能让 Jest 找到我的测试,我尝试将测试移动到默认测试目录,但它们仍然失败。

我想澄清一下,测试本身运行良好,问题似乎是我导入的模块之一使用 ES6,在我上面的示例中,如果我不导入我的轮播组件,测试运行良好,尽快当我导入该文件中的导入语句时,测试会阻塞。似乎导入的模块没有被转译。

更新 #2

经过一番调查,问题似乎是 babel 没有在 node_modules 中转译 ES6。我在这里创建了一个示例 repo 来演示这一点: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 部分时会发生什么。这在简单的情况下不需要。 @AndreasKöberle 我得到了同样的错误,是的,你的权利我似乎不需要它 你试过在没有jest.conf.js的情况下运行吗?它应该可以在没有额外配置的情况下工作 我怀疑 textRegex 和/或 transform 是问题的根源 你可以在这里验证github.com/MinimalNoise/persist-lead-service,测试完全通过es-modules(虽然没有jsx)没有任何特定的jest配置 【参考方案1】:

您可以尝试将 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(您可能需要在更改 babel 配置后第一次将 --no-cache 标志添加到命令中,因为 Jest 缓存 babel 输出,但之后您可以将其关闭:

NODE_ENV=test jest --no-cache

我在 Frontend Masters 的 Brian Holt 的 React 研讨会上了解到这个问题。 https://frontendmasters.com/courses/

【讨论】:

谢谢@A。 Cookro 我之前尝试过,只是再次尝试并没有运气,babel 似乎仍然在忽略 node_modules 中的文件。 在尝试了 10 种不同的方法之后,这个解决方案是唯一一个在 ES6 导入中表现正常的解决方案【参考方案2】:

我遇到了同样的问题(node_module 没有被 babel-jest 转译),但无法解决。

相反,我终于通过模拟 node_module 成功了,就像这里描述的 https://facebook.github.io/jest/docs/manual-mocks.html

注意:在 __mocks__ 子文件夹中设置模拟对我不起作用。所以我将模拟作为jest.mock() 函数的第二个参数传递。类似的东西:

    jest.mock('your_node_module', () => )

【讨论】:

谢谢,我会试试这个解决方案,让你知道效果如何。【参考方案3】:

默认情况下,babel-jest 会忽略 node_modules 中的任何代码,请参阅 Jest 配置选项 transformIgnorePatterns。我还创建了一个PR on your example repo,所以你可以看到它在工作。

虽然这可行,但我发现它在具有大量包含 ES 模块的依赖项的实际应用程序中非常慢。 Jest 代码库对此略有不同,您可以在babel-jest transforming dependencies 中找到。这在 Windows 上也可能需要更长的时间,请参阅 Taking 10 seconds on an empty repo。

如果进行“单元”测试,模拟可能是更好的方法。

【讨论】:

谢谢,我还没来得及查看 PR,但我会​​的。我曾尝试使用许多 Jest 选项,包括我相信的 transformIgnorePatterns,但我可能做错了什么,所以会检查一下。 终于有时间检查 PR 并接受了,我现在可以正常运行测试了。碰巧我们暂时坚持使用我们的 Karma/Jasmine 堆栈。为了其他人的利益,以下配置可以解决此问题: `"jest": "transformIgnorePatterns": [ "/node_modules/(?!test-component).+\\.js$" ] , @jamiedust 如果贡献者分享他们的观点,他们可能希望确保将给定的信息传达给其他人。删除包含相关 PR 的存储库对任何人都没有帮助。 @oyilmaztekin 这是一个公平的观点,我在删除该回购时没有考虑到这一点,抱歉。但是请注意,我确实在我的最后一条评论中放置了相关的配置:在 package.json "jest": "transformIgnorePatterns": [ "/node_modules/(?!test-component).+\\.js$" ] 【参考方案4】:

另一个可能的原因。 Babel 现在会忽略 node_modules 中的 .babelrc 并使用依赖项提供的那个。如果您可以控制依赖项,则必须向其添加 .babelrc,babel 将为其使用这些设置。

如果您的依赖项和项目使用不同的 babel 版本或模块,这可能会导致问题。

【讨论】:

【参考方案5】:

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

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

【讨论】:

以上是关于babel-jest 不处理模块内的 ES6的主要内容,如果未能解决你的问题,请参考以下文章

处理 es6 模块中的依赖关系,用于节点和浏览器

VUE学习笔记:19.模块化开发之webpack处理ES6语法

Webpack 模块处理

babel-jest ES2015 导入语句

nodejs和es6模块化的不同

如何优雅的处理Nodejs中的异步回调