运行 js 测试 - 获取 "Cannot use import statement outside of a module"

Running js tests - getting "Cannot use import statement outside of a module"

我添加了 type: module 但这没有帮助。

我正在尝试 运行 使用 importexport 作为源文件的 mocha 或 jest 测试。

关于此的现有问题具有与我的不同的细节,我也发现对于具有我特定情况的人来说,这些问题令人困惑,特别是因为我已经制定了一个具体的答案,其中的细节与现有问题无关,但是与我处境中的其他人相关。

您需要使用编译器,然后在运行测试时使用编译后的文件。

很多参考文献都说要加type: module,但不多说了。
明确一点,基本信息:

SyntaxError: Cannot use import statement outside a module

是因为您正在使用 import/export 并且 您正在尝试直接 运行 文件而无需编译。

这里的思维转变是习惯于在一个目录中编辑文件,运行在另一个目录中进行测试。或者,一些解决方案提供 "in'flight" 编译,因此这个细节基本上是隐藏的,只使用源文件。

根据具体需要,有几种不同的方法可以做到这一点。这是迄今为止我发现的最简单的方法之一,使用 Babel 进行编译步骤:

  • 安装 babel npm install babel --save-dev
  • package.json脚本中添加babel命令,例如:

    "scripts": {
      "test": "babel src/ --out-dir lib --presets=@babel/env; jest lib/*.test.js",
      "build": "babel src/ --out-dir lib --presets=@babel/env"
    },  // this was for jest but you can use mocha, etc as needed
        // Note that using preset this way eliminates the need for a specific .babel.config.json file
    

现在,如果你 运行:

jest .

你得到SyntaxError: Cannot use import statement outside a module,但如果你运行 npm t你得到

Successfully compiled 2 files with Babel.
 PASS  lib/app.test.js
  All tests
    ✓ Canary test (2ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total

展望未来,请记住:

  • 编辑 src/
  • 中的文件
  • 运行 测试 lib/

根据 the Jest documentation, if you make sure babel-jest is installed and supply your Babel configuration per the Babel documentation,在配置文件中或 package.json 例如:

.babelrc.json

{
  "presets": [
    "@babel/env"
  ]
}

然后 babel-jest 将自动获取它,您无需显式预构建文件来测试它们。这也意味着您不必在调用 Babel 时在命令行上设置标志。


请注意,如果您确实想要明确预构建,我建议:

  1. 使用 pre<script> 脚本而不是在一行中包含多个步骤;和
  2. 重新使用 build 脚本,这样您就不必在两个地方进行更改。

你的情况:

"scripts": {
  "build": "babel src/ --out-dir lib",
  "pretest": "npm run build",
  "test": "jest lib/*.test.js"
}

过去,如果不使用 Babel 转译代码,就无法在 Node 中使用 ES 模块(即 import/export)。然而,Node 中对 ES 模块的支持现在已经成为现实,Jest 和 Mocha 最近也都添加了对原生使用 ES 模块的支持。

然而,这不仅仅是将 "type": "module" 添加到您的 package.json

在 Jest 中使用原生 ES 模块的步骤

  1. 如前所述,将 "type": "module" 添加到您的 package.json

  2. jest-environment-nodejest-environment-jsdom-sixteen 安装到您的开发依赖项中。例如:

    $ npm i -D jest-environment-node
    
  3. 更新 package.json 中的 Jest 配置并添加 testEnvironment 设置。例如:

    "jest": {
        "testEnvironment": "jest-environment-jsdom-node"
    }
    
  4. 如果您使用的是 13.2 之前的 Node 版本,那么在 运行ning Node 时需要添加两个额外的标志:--experimental-modulesexperimental-vm-modules.我使用 npx 来执行命令,尽管它有点冗长:

    $ npx --node-arg=--experimental-modules --node-arg=--experimental-vm-modules jest
    

这将 运行 您所有的 Jest 测试都使用适当的节点标志。如果这是您的方式,我建议您在 package.json 中将其作为您的 test 脚本。

现在你应该可以在没有 Babel 的情况下使用 import/export

最后一点很重要:在 Node 中使用原生 ES 模块时,您必须使用本地模块的整个导入路径,包括文件扩展名。例如:

import lib from "./my/lib.js"

这里是关于原生 ES 模块的 Node 文档,如果您想阅读更多详细信息:https://nodejs.org/dist/latest-v14.x/docs/api/esm.html

我还建议通读这个 Github 问题以获取有关本机 ES 模块的 Jest 实现的更多详细信息:https://github.com/facebook/jest/issues/9430