运行 使用 Jest 测试时无法使用 uuid 模块
Can't use uuid module when running tests with Jest
我有一个使用 Express 4.17.1
的非常简单的 Node.js (12.16.3
) 应用程序。我正在尝试使用 Jest 26.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
...一切正常。我很困惑......我不明白为什么只有 Jest 会失败。我还需要做些什么才能让它发挥作用吗?
我的回答是旁注,但我怀疑问题的性质与 import { v4 } from "uuid"
.
的导入语法有关
例如那里有一个相关的警告:
(node:74672) ExperimentalWarning: The ESM module loader is experimental.
通常捆绑的 JavaScript 与模块加载到 Jest 系统的方式之间可能存在细微的不一致。因此,解决方案可能涉及添加到配置文件中——这样 Jest 就可以理解 ESM 语法。例如这里有一个有趣的答案:
Related MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
The import statement cannot be used in embedded scripts unless such script has a type="module". Bindings imported are called live bindings because they are updated by the module that exported the binding.
作为测试,您可以看看像这样导入它是否会有所不同:
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 加载器”相关的整个 class 问题。
问题是 Jest
和 uuid
之间的版本不兼容。 uuid 版本 8 支持原生 ES 模块,而 Jest 版本 26 不支持。
您始终可以使用以下语法 uuid 版本 3.x.x:
const uuid = require('uuid/v4');
uuid(); // ⇨ '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'
TL;DR: Jest 尚不支持 package.json
中的字段 "exports"
。
问题是 Node.js 使用 ESM 版本,因为它理解 package.json 中的 "exports" 字段,但由于 Jest 尚不支持它,Jest 使用 [= package.json 中的 55=] 字段导出 CommonJS 版本。见 the relevant package.json section:
...
"main": "./dist/index.js",
"exports": {
"./package.json": "./package.json",
".": {
"require": "./dist/index.js",
"import": "./wrapper.mjs"
}
},
...
这是做什么的:
- 默认导出为
main
,一如既往。
- 如果
exports
被理解,那将覆盖 "main"
exports
- 默认的 exports
"."
定义了一个 require 和 import,所以 Node.js 使用 "import"
- 但问题是 the Jest issue 表示它还不理解 "Package Exports",因此 Jest 正在尝试加载 CommonJS 文件(来自 "main"),而 Node.js 加载 ESM 文件。
我found the exact same issue and documented it here。作为实验,这应该适用于 Jest:
import uuid from 'uuid';
const { v4 } = uuid;
但这不适用于 Node.js since UUID does not define a default export。
你有两个现实的选择:
- 等到 Jest 支持包导出,他们在 ESM 支持方面做得很好,我认为这不会花很长时间。
- Upvote my proposal 在
uuid
包中,它们还导出默认值,如 wrapper.mjs
中的 export default uuid
,这将允许您使用我在上面放置的代码段。
我有一个使用 Express 4.17.1
的非常简单的 Node.js (12.16.3
) 应用程序。我正在尝试使用 Jest 26.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
...一切正常。我很困惑......我不明白为什么只有 Jest 会失败。我还需要做些什么才能让它发挥作用吗?
我的回答是旁注,但我怀疑问题的性质与 import { v4 } from "uuid"
.
例如那里有一个相关的警告:
(node:74672) ExperimentalWarning: The ESM module loader is experimental.
通常捆绑的 JavaScript 与模块加载到 Jest 系统的方式之间可能存在细微的不一致。因此,解决方案可能涉及添加到配置文件中——这样 Jest 就可以理解 ESM 语法。例如这里有一个有趣的答案:
Related MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
The import statement cannot be used in embedded scripts unless such script has a type="module". Bindings imported are called live bindings because they are updated by the module that exported the binding.
作为测试,您可以看看像这样导入它是否会有所不同:
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 加载器”相关的整个 class 问题。
问题是 Jest
和 uuid
之间的版本不兼容。 uuid 版本 8 支持原生 ES 模块,而 Jest 版本 26 不支持。
您始终可以使用以下语法 uuid 版本 3.x.x:
const uuid = require('uuid/v4');
uuid(); // ⇨ '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'
TL;DR: Jest 尚不支持 package.json
中的字段 "exports"
。
问题是 Node.js 使用 ESM 版本,因为它理解 package.json 中的 "exports" 字段,但由于 Jest 尚不支持它,Jest 使用 [= package.json 中的 55=] 字段导出 CommonJS 版本。见 the relevant package.json section:
...
"main": "./dist/index.js",
"exports": {
"./package.json": "./package.json",
".": {
"require": "./dist/index.js",
"import": "./wrapper.mjs"
}
},
...
这是做什么的:
- 默认导出为
main
,一如既往。 - 如果
exports
被理解,那将覆盖"main"
exports - 默认的 exports
"."
定义了一个 require 和 import,所以 Node.js 使用 "import" - 但问题是 the Jest issue 表示它还不理解 "Package Exports",因此 Jest 正在尝试加载 CommonJS 文件(来自 "main"),而 Node.js 加载 ESM 文件。
我found the exact same issue and documented it here。作为实验,这应该适用于 Jest:
import uuid from 'uuid';
const { v4 } = uuid;
但这不适用于 Node.js since UUID does not define a default export。
你有两个现实的选择:
- 等到 Jest 支持包导出,他们在 ESM 支持方面做得很好,我认为这不会花很长时间。
- Upvote my proposal 在
uuid
包中,它们还导出默认值,如wrapper.mjs
中的export default uuid
,这将允许您使用我在上面放置的代码段。