使用 Jest 运行测试时无法使用 uuid 模块



我有一个非常简单的Node.js(12.16.3(应用程序,它使用Express4.17.1。我正在尝试使用 Jest26.0.1来运行测试套件,但由于整个项目中使用的uuid模块(版本8.1.0(存在一些问题,同样失败了:

[x80486@uplink:~/Workshop/node-guacamole]$ npm run test 
> node-guacamole@0.3.0 test /home/x80486/Workshop/node-guacamole
> node --experimental-modules --experimental-vm-modules ./node_modules/.bin/jest --coverage --detectOpenHandles --forceExit --verbose
(node:71155) ExperimentalWarning: The ESM module loader is experimental.
FAIL  src/domain/customer.test.js
● Test suite failed to run
SyntaxError: The requested module 'uuid' does not provide an export named 'v4'
at jasmine2 (node_modules/jest-jasmine2/build/index.js:228:5)
FAIL  src/service/customer.service.test.js
● Test suite failed to run
SyntaxError: The requested module 'uuid' does not provide an export named 'v4'
at async Promise.all (index 4)
at jasmine2 (node_modules/jest-jasmine2/build/index.js:228:5)
FAIL  src/handler/customer.handler.test.js
● Test suite failed to run
SyntaxError: The requested module 'uuid' does not provide an export named 'v4'
at async Promise.all (index 2)
at async Promise.all (index 7)
----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |       0 |        0 |       0 |       0 |                   
----------|---------|----------|---------|---------|-------------------
Test Suites: 3 failed, 3 total
Tests:       0 total
Snapshots:   0 total
Time:        0.63 s
Ran all test suites.

我正在导入模块,例如:import { v4 } from "uuid"; 另一方面,应用程序成功运行:

[x80486@uplink:~/Workshop/node-guacamole]$ npm run start:dev 
> node-guacamole@0.3.0 start:dev /home/x80486/Workshop/node-guacamole
> nodemon --experimental-modules --experimental-vm-modules ./src/main.js
[nodemon] 2.0.4
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node --experimental-modules --experimental-vm-modules ./src/main.js`
(node:74672) ExperimentalWarning: The ESM module loader is experimental.
2020-06-03T03:28:48.889Z [debug] - Server running at http://localhost:8080
2020-06-03T03:28:48.889Z [info] - Press CTRL-C to stop

。一切正常。我很困惑...我不明白为什么这只在开玩笑中失败了。我还需要做些什么来使其工作吗?

TL;DR:开玩笑还不支持package.json中的现场"exports"

问题是 Node.js 使用 ESM 版本,因为它理解 package.json 中的"export"字段,但由于 Jest还不支持它,Jest 使用 package.json 中的"main"字段导出 CommonJS 版本。请参阅相关的 package.json 部分:

...
"main": "./dist/index.js",
"exports": {
"./package.json": "./package.json",
".": {
"require": "./dist/index.js",
"import": "./wrapper.mjs"
}
},
...

这是做什么的:

  1. 默认导出为main,与往常一样。
  2. 如果理解exports,则会覆盖"main"导出
  3. 默认导出"."定义了需求和导入,因此 Node.js 使用"导入">
  4. 但问题是 Jest 问题表明它还没有理解"包导出",所以 Jest 正在尝试加载 CommonJS 文件(从"主"(,而 Node.js 加载 ESM 文件。

我发现了完全相同的问题并在此处记录了它。作为一个实验,这应该适用于Jest:

import uuid from 'uuid';
const { v4 } = uuid;

但这不适用于 Node.js因为 UUID 没有定义默认导出。

您有两个现实的选择:

  • 等到Jest支持包导出,他们在ESM支持方面做得很好,我认为这不会花很长时间。
  • uuid包中对我的提议投赞成票,他们也导出默认值,例如wrapper.mjs中的export default uuid,这将允许您使用我上面放置的代码片段。

问题是Jestuuid之间的版本不兼容。 uuid 版本 8 支持本机 ES 模块,而 Jest 版本 26 不支持。

始终可以使用以下语法进行 uuid 版本 3.x.x:

const uuid = require('uuid/v4');
uuid(); // ⇨ '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'

uuid 包导入可以用模拟来覆盖,从而消除错误。

// In your .test.tsx file
jest.mock('uuid', () => ({ v4: () => '00000000-0000-0000-0000-000000000000' }));

我的回答是旁注,但我怀疑问题的性质与import { v4 } from "uuid"的导入语法有关。

例如,那里有一个相关的警告:

(节点:74672( 实验性警告:ESM 模块加载器是实验性的。

正常捆绑的 JavaScript 与模块加载到 Jest 系统的方式之间可能存在细微的不一致。因此,解决方案可能涉及添加到配置文件中 - 因此Jest可以理解ESM语法。例如,这里有一个有趣的答案:ts-jest 不识别 es6 导入

相关 MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import

import 语句不能在嵌入式脚本中使用,除非此类脚本具有 type="module"。导入的绑定称为实时绑定,因为它们由导出绑定的模块更新。

作为测试,您可以查看像这样导入它是否有区别:

const { v4: uuidv4 } = require('uuid');
const v4 = uuidv4;

const v4 = require('uuid').v4 // might work as well

如果它有效,我不建议使用它,但它应该将其缩小到绝对的语法。

问题源于这里的这个文件:在我看来 https://github.com/uuidjs/uuid/blob/master/src/index.js,因为该文件是传递的(大致类似于符号链接(,所以 Jest 正在尝试导入导出的导出。

这可能与 Babel 和缺乏变身装置有关。正确修复它应该可以缓解与"ESM加载程序"相关的整类问题。

最新更新