Jest设置"SyntaxError:意外的令牌导出"

Cor*_*son 25 reactjs jestjs redux

我正在对目前没有测试的现有项目进行测试.我的测试无法编译node_modules/导入.

/Users/me/myproject/node_modules/lodash-es/lodash.js:10
export { default as add } from './add.js';
^^^^^^
SyntaxError: Unexpected token export

  at transformAndBuildScript (node_modules/jest-runtime/build/transform.js:320:12)
  at Object.<anonymous> (app/reducers/kind_reducer.js:2:43)
  at Object.<anonymous> (app/reducers/index.js:12:47)
Run Code Online (Sandbox Code Playgroud)

我发现的解决方法是node_modules在package.json jest配置中'whitelist' ,如下所示:

"jest": {
    "transformIgnorePatterns": [
      "!node_modules/"
    ]
  }
Run Code Online (Sandbox Code Playgroud)

这似乎是一个黑客,因为它需要超过1分钟来运行一个简单的导入测试node_modules/lodash-es/lodash.js.

感谢任何帮助或方向,谢谢!

Yan*_*Tay 29

我不得不把这个添加到我的.jestconfig:

"transformIgnorePatterns": [
  "<rootDir>/node_modules/(?!lodash-es)"
]
Run Code Online (Sandbox Code Playgroud)

  • 这有效,但我必须安装`babel-jest`、`babel-preset-env`、`babel-preset-react`,然后`"transform": { "^.+\\.(js|jsx| mjs)$": "&lt;rootDir&gt;/node_modules/babel-jest" }`,因为 ts 和 js 文件需要不同的转换。 (4认同)
  • 如果您有多个,您可能需要包含在相同的正则表达式中,例如“(?!lodash-es|my-module)”。由于某种原因,如果它们位于单独的条目中,它们就会相互抵消。 (4认同)
  • 扩展一下 Jazzy 的评论:如果你_已经_有一个 `transformIgnorePatterns: [ 'node_modules/(?!foo|bar)' ]` 条目,那么你**必须将 `lodash-es` 添加到该列表**;您无法在transformIgnorePatterns数组中添加单独的条目,因为现有条目已经意味着“忽略node_modules下除foo和bar之外的所有文件夹”,因此node_modules/lodash-es将被忽略。// 提示(来自 [github 问题评论](https://github.com/nrwl/nx/issues/812#issuecomment-429420861)):如果使用 jest.config.js,您可以执行 `const esModules = [' foo', 'bar', 'lodash-es']` 然后是 `esModules.join('|')` (3认同)
  • 注意:如果您已经运行了“jest --watch”,则必须退出并重新运行 jest,然后才能看到“transformIgnorePatterns”更改生效。 (3认同)
  • 由于 jest 文档中的这一声明,它们必须位于同一条目中。“如果测试路径与任何模式匹配,则不会对其进行转换。” 因此,当测试 my-module 时,它​​会测试 ?!lodash-es 正则表达式为 true,并且会被忽略。 (2认同)
  • @BhushanPatil 这将添加到您的 Jest 配置文件中,该文件可以在您的 package.json 或单独的 jest.config.js 文件(及其变体)中定义。更改位置取决于您的 Jest 配置所在的位置。 (2认同)

OPa*_*tel 17

如果以上解决方案都不适合您,则可以开玩笑地尝试一下

"moduleNameMapper": {
    "^lodash-es$": "lodash"
}
Run Code Online (Sandbox Code Playgroud)

lodash-es在测试运行时,它将替换为commonjs版本。

  • 我讨厌这是唯一对我有用的答案。必须有比两次将 lodash 作为依赖项更好的方法 (8认同)
  • 谢谢,这是唯一对我有用的解决方案。“transformIgnorePatterns”方法对我不起作用。 (5认同)
  • @jamesthollowell,你只需要 `devDependency` 中的 `lodash` 来进行测试。所以它不会影响您的捆绑包大小。您仍然可以在整个应用程序中使用“lodash-es”导入。 (4认同)
  • @jamesthollowell 你不必直接依赖它,因为你很可能已经通过另一个包深深依赖它。我真的不建议这样做,但是如果您不想在 pkg.json 中添加另一个条目,则可以这样做。 (2认同)
  • 该解决方案似乎比“transformIgnorePatterns”明显更快。(我的测试套件使用此命令运行大约需要 17 秒,使用“transformIgnorePatterns”运行大约需要 23 秒。) (2认同)

Lew*_*ung 14

在这里发布更完整的答案:

默认情况下,Jest不会转换node_modules,因为node_modules很大.大多数节点模块都被打包以暴露ES5代码,因为它可以在没有任何进一步转换的情况下运行(并且在很大程度上向后兼容).

在您的情况下,lodash-es专门公开ES模块,这需要由Jest通过babel构建.

您可以尝试缩小白名单,以便Jest不会尝试通过babel传递node_modules中的每个javascript文件.

我认为你的案例中的正确配置是:

"jest": {
  "transformIgnorePatterns": [
    "/!node_modules\\/lodash-es/"
  ]
}
Run Code Online (Sandbox Code Playgroud)

  • 看来正则表达式不正确,所以 babel 不仅会转换 lodash-es 文件夹,还会转换 node_modules 文件夹内的所有模块。这并不理想。我认为正确的正则表达式应该是“&lt;rootDir&gt;/node_modules/(?!lodash-es)” (2认同)

8bi*_*oey 13

对于create-react-app正在寻找修复程序的用户,以下是对我有用的方法:

// package.json
...
  "jest": {
    "transformIgnorePatterns": [
      "<rootDir>/node_modules/(?!lodash-es)"
    ]
  },
...
Run Code Online (Sandbox Code Playgroud)

覆盖jest.config.js文件中的选项对我不起作用。请记住,并非每个选项都可以被覆盖,这里是支持的选项列表:https ://create-react-app.dev/docs/running-tests#configuration


San*_*rma 7

重命名.babelrcbabel.config.js添加transformIgnorePatterns对我有用。

module.exports = {
  "presets": ["@babel/preset-env"]
}
Run Code Online (Sandbox Code Playgroud)

PS 我的笑话版本是:

"jest": "24.9.0"
Run Code Online (Sandbox Code Playgroud)

使用 Babel 7 时,babel-jest 不会在 node_modules 中转译导入/导出


And*_*cha 7

可能有人觉得这很有用:

就我而言,我有一个使用lodash-espackage.json 的 Angular 应用程序。在测试过程中,我也遇到了和作者一样的错误。

OPatel 的答案对我来说效果很好,只需稍加调整(将其添加到您的jest.config.ts):

"moduleNameMapper": {
    "lodash-es": "lodash"
}
Run Code Online (Sandbox Code Playgroud)

更改后,我还需要将 添加"esModuleInterop": true到我的tsconfig.spec.json属性中compilerOptions以摆脱TypeError: cloneDeep_1.default is not a function.

更新:

在上述解决方案之后,所有 lodash 方法都返回 LodashWrapper 而不是实际值,例如

const clone = cloneDeep(object); // LodashWrapper
Run Code Online (Sandbox Code Playgroud)

为了摆脱这个问题,我使用了这个解决方案: https://github.com/nrwl/nx/issues/812#issuecomment-787141835

moduleNameMapper: {
    "^lodash-es/(.*)$": "<rootDir>/node_modules/lodash/$1",
}
Run Code Online (Sandbox Code Playgroud)