Jest支持ES6的import/export吗?

185

如果我在ES6中使用import/export,则我的所有Jest测试都会失败,并显示错误:

意外的保留字

当我将要测试的对象转换为旧式的IIFE语法时,突然我的测试通过了。或者,采用更简单的测试用例:

   var Validation = require('../src/components/validation/validation'); // PASS
   //import * as Validation from '../src/components/validation/validation' // FAIL

同样的错误。显然这里存在着导入/导出问题。为了让我的测试框架正常工作,重写我的代码使用 ES5 语法是不现实的。

我有 babel-jest。我尝试了来自 GitHub 问题页面的各种 建议,但到目前为止都无法解决问题。

文件package.json

 "scripts": {
    "start": "webpack-dev-server",
    "test": "jest"
  },
      "jest": {
        "testPathDirs": [
          "__tests__"
        ],
        "testPathIgnorePatterns": [
          "/node_modules/"
        ],
        "testFileExtensions": ["es6", "js"],
        "moduleFileExtensions": ["js", "json", "es6"]
      },

文件 babelrc

{
  "presets": ["es2015", "react"],
  "plugins": ["transform-decorators-legacy"]
}

有没有解决方法?


这个链接有帮助吗? - user3854359
1
@GeorgePompidou - 可能吧。我不确定这个解决方案是否适用于babel-jest。 - P.Brian.Mackey
这只是一个指定类似 "presets": ["es2015"] 的事情,可以在 package.json 或者 .babelrc 文件中完成。毕竟你正在使用 babel。 - user3854359
这个问题在这里有人通过安装babel-preset-es2015和babel-preset-react包解决了。如果我没有提供太多帮助,很抱歉--我没有遇到过这个问题。 - user3854359
5
这个问题是5年前的,然而jest对ES模块的支持仍然是实验性的。 - aderchox
显示剩余4条评论
13个回答

179

我的回答到另一个问题,这可以更简单:


唯一的要求是将您的test环境配置为Babel,并添加ECMAScript 6转换插件:


第1步:

在项目根目录中的.babelrc中添加您的test环境:

{
  "env": {
    "test": {
      "plugins": ["@babel/plugin-transform-modules-commonjs"]
    }
  }
}

步骤2:

安装ECMAScript 6转换插件:

npm install --save-dev @babel/plugin-transform-modules-commonjs

就是这样。 Jest将自动启用从ECMAScript模块到CommonJS的编译,无需在package.json中的jest属性中添加其他选项。


35
如果你不想使用.babelrc污染你的项目,你可以在package.json文件中的babel键下面添加env键。 - Dan Dascalescu
6
我相信较新的 @babel/plugin-transform-modules-commonjs 取代了 transform-es2015-modules-commonjs - Albizia
3
这真是花了我很长时间!谢谢! - Qamar Stationwala
2
这应该是正确的答案,非常简单。 - Ben Steward
1
@P.Brian.Mackey 当然可以!如果您已经测试了新方法,并且不再需要Babel,那么这是个好消息,重要的是要向社区更新有关更新方法的信息。 :) - Paulo Coghi
显示剩余6条评论

123

2020更新 - ECMAScript模块(ESM)的本地支持


根据此问题,从jest@25.4.0开始,原生支持ESM。所以您将不再需要使用babel。在撰写本答案时(05/2020),要激活它,您需要执行三个简单的步骤:

  • 确保通过在配置文件中设置transform:{}来不转换import语句
  • 使用--experimental-vm-modules标志运行node@^12.16.0 || >=13.2.0
  • 使用jest-environment-nodejest-environment-jsdom-sixteen运行测试。

因此,您的Jest配置文件应至少包含以下内容:

export default {
    testEnvironment: 'jest-environment-node',
    transform: {}
    ...
};

要设置--experimental-vm-modules标志,您需要按以下方式运行Jest:

node --experimental-vm-modules node_modules/jest/bin/jest.js

另外需要注意的是,在 Github 的问题中提到,这种方法还不支持 jest 对象。因此,您可能需要手动导入它:

Also note in the Github issue that this approach does not yet support the jest object. So you may need to import it manually:

import {jest} from '@jest/globals'

(我希望这种情况将来会改变)


3
'jest-environment-node'是什么,它与环境中的'node'有何不同? - akauppi
26
“NODE_OPTIONS='--experimental-vm-modules' jest” 更加简洁地运行jest。 - Relisora
9
重要提示:目前原生支持的功能中还不包括模拟。 - Justin Dalrymple
5
让这个工作起来的第四步是:在package.json文件中添加"type": "module",以便Node将文件识别为ESM格式。详见https://nodejs.org/api/packages.html#packages_determining_module_system。 - Louis Ameline
3
我只需要在 v14.6.1 版本的 Node 和 v26.6.3 版本的 Jest 上运行 NODE_OPTIONS='--experimental-vm-modules' jest,无需进行任何配置。 - Raine Revere
显示剩余5条评论

41

为了更新配置,我正在使用https://babeljs.io/setup#installation

选择JEST并快乐吧:

当前配置供参考:

npm install --save-dev babel-jest

在你的 package.json 文件中,进行以下更改:

{
  "scripts": {
    "test": "jest"
  },
  "jest": {
    "transform": {
      "^.+\\.jsx?$": "babel-jest"
    }
  }
}

安装Babel预设:

npm install @babel/preset-env --save-dev

创建一个.babelrc文件:

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

运行您的测试:

npm run test

对我有用!Babel文档已更新,正则表达式中也指定了.ts文件。不需要像ts-jest这样的其他TypeScript依赖项。但我确实需要@babel/preset-typescript。将其添加到.babelrc文件的预设列表中即可。 - Mayowa Daniel
1
这基本上是正确的答案。这里有另一个好的参考页面,来自Jest官方文档 https://jestjs.io/docs/getting-started#using-babel - Colin D
1
谢谢,这对我有用。目前为止,您不需要transform添加到您的package.json中。它现在是默认设置。 - Scott Coates

9
package.json中,请设置如下内容:"test": "node --experimental-vm-modules node_modules/.bin/jest"。应该就可以了!

4
不行!我不会这样做!嘲讽是行不通的。 - avepr
很抱歉听到这个消息。使用jest有一些微妙之处,即使在Windows和Mac上也可能会出现问题。不知道你具体想做什么,但是这里有一个模板存储库,我用它来处理Node相关的东西,其中包含一个完全工作的jest(使用nodemon)。它还包括其他你可能需要或不需要的东西,但至少可以用作指南? - CodeFinity
我跟随了这个答案。https://dev59.com/vlsV5IYBdhLWcg3w0hlU#52224329 基本上使用babel将所有内容转换回commonjs。 - avepr
没错,那就是该仓库最终要做的事情。 - CodeFinity

3

只需要将 stage-0 添加到您的 .babelrc 文件中即可。以下是一个示例:

{
  "presets": ["es2015", "react", "stage-0"],
  "plugins": ["transform-decorators-legacy"]
}

1
请安装stage-0预设,通过npm安装。 - Razvan Antalut
4
不要在生产环境中使用 stage-0 或任何 stage-*。这种做法不好。请使用 preset-env - fregante

3

就目前而言,使用Node 16和Jest 29,我只需要按照以下方式定义一个测试脚本:

package.json

"type": "module",
...
"scripts": {
    ...
    "test": "NODE_OPTIONS='--experimental-vm-modules' jest ."
  },

我刚在一个新项目中尝试了这个,但它不起作用。 - sc3000
这对我起作用了! - undefined

3
我也遇到了相同的问题。
以下是我所做的操作:
运行命令:yarn add --dev babel-jest @babel/core @babel/preset-envrootDir下创建文件jest.config.js
module.exports = {
    moduleFileExtensions: ["js", "json", "jsx", "ts", "tsx", "json"],
    transform: {
        '^.+\\.(js|jsx)?$': 'babel-jest'
    },
    testEnvironment: 'node',
    moduleNameMapper: {
        '^@/(.*)$': '<rootDir>/$1'
    },
    testMatch: [
        '<rootDir>/**/*.test.(js|jsx|ts|tsx)', '<rootDir>/(tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx))'
    ],
    transformIgnorePatterns: ['<rootDir>/node_modules/']
};

接下来在rootDir中创建一个名为babel.config.js的文件。

操作如下:

module.exports = {
    "presets": ["@babel/preset-env"]
}

1
所有内容都在Jest文档中解释了:Jest文档

1.

npm install --save-dev babel-jest @babel/core @babel/preset-env
  1. in file: babel.config.js

    module.exports = {
      presets: [['@babel/preset-env', {targets: {node: 'current'}}]],
    };
    

1
以下是我为我的项目设置jest、typescript和ES模块的方法。
jest.config.js
/**
 * @type {import('ts-jest/dist/types').InitialOptionsTsJest} 
 * To configure ESM support, see: https://kulshekhar.github.io/ts-jest/docs/guides/esm-support
 * 
 **/
export default {
    preset: 'ts-jest/presets/default-esm',
    testEnvironment: 'node',
    extensionsToTreatAsEsm: ['.ts'],
    globals: {
        'ts-jest': {
            useESM: true
        }
    },
    setupFiles: ['<rootDir>/__tests__/setup.ts'],
};

tsconfig.json

{
    "compilerOptions": {
        "target": "ESNext",
        "module": "ESNext",
        "outDir": "./dist",
        "moduleResolution": "node",
       // "strict": true,
        "esModuleInterop": true,
        "inlineSourceMap": true,
    }
}

package.json中的脚本和devDependencies

"scripts": {
    "start": "node ./dist/server.js",
    "dev": "tsc-watch --onSuccess \"node ./dist/server.js\"",
    "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest"
  },
"devDependencies": {
    "@jest/globals": "^27.4.4",
    "@types/express": "^4.17.13",
    "@types/jest": "^27.4.0",
    "@types/supertest": "^2.0.11",
    "cross-env": "^7.0.3",
    "supertest": "^6.2.1",
    "ts-jest": "^27.1.3"
  }

__tests__/setup.ts

import dotenv from 'dotenv';


dotenv.config({
    path: './.env.test'
});

如果是JS而不是TS,您将如何指定ESM模块? - Petruza
你是什么意思?我不明白。 - Gilbert
我的意思是,如果使用JS而不是TS,这个方法会起作用吗?因为我尝试使用带有ES6模块的JS代码进行Jest测试,但Jest甚至无法识别import关键字,并抱怨未知标记。 - Petruza
1
@Petruza 当然 Jest 识别 import 关键字。你只需要使用 experimental-vm-modules 参数。顺便说一下,你要确保 Jest 的目标是已经编译成 JavaScript 而不是尚未编译的 TypeScript。虽然源代码是 TypeScript,但你的测试可以用 JavaScript 编写。 - Gilbert

0
为了支持React和react-testing-library,可能需要弹出CreateReactApp并从package.json中获取所有必需的Jest配置。 它可以与另一个打包程序Rollup一起使用,这是我的情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接