jest fails with error: Cannot find module 'jose-node-cjs-runtime/jwt/sign'
jest fails with error: Cannot find module 'jose-node-cjs-runtime/jwt/sign'
我正在用玩笑测试我的 Node.js API。 API 是一个用于管理任务的 Express 应用程序。它具有 signup/login 功能,仅允许经过身份验证的用户使用该应用程序。它有一个用于注册新用户的端点,并且存在许多使用快速中间件通过 JWT 验证用户身份验证的端点。我安装了 jose-node-cjs-runtime@^3.15.5
包,用于 JWT 生成和验证。
如果我 运行 使用 dev
脚本 env-cmd -f ./config/dev.env nodemon src/index.js
的项目,没有问题,运行 没问题。我正在尝试使用 jest 测试文件来测试用户注册,该文件使用 superagent
包来测试端点。我正在使用测试脚本 env-cmd -f ./config/test.env jest --watch
来 运行 测试。此命令显示以下错误并且测试失败:
FAIL tests/user.test.js
● Test suite failed to run
Cannot find module 'jose-node-cjs-runtime/jwt/sign' from 'src/models/user.js'
Require stack:
src/models/user.js
src/routers/user.js
src/app.js
tests/user.test.js
3 | const bcrypt = require('bcryptjs');
4 | // library for signing jwt
> 5 | const { SignJWT } = require('jose-node-cjs-runtime/jwt/sign');
| ^
6 | // library for generating symmetric key for jwt
7 | const { createSecretKey } = require('crypto');
8 | // task model
at Resolver.resolveModule (node_modules/jest-resolve/build/resolver.js:313:11)
at Object.<anonymous> (src/models/user.js:5:21)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 3.385 s
Ran all test suites related to changed files.
我无法弄清楚为什么会导致此错误。请帮助我找到解决方案。
我使用的是 Node.js 版本 16.7.0,但遇到了这个错误。我今天升级了 Node.js 版本。我当前的 Node.js 版本是 16.9.0。升级 Node.js 版本后,我也收到此错误。以下是项目的 package.json 文件内容:
{
"name": "task-manager",
"version": "1.0.0",
"description": "",
"main": "index.js",
"engines": {
"node": ">=16.7.0"
},
"scripts": {
"start": "node src/index.js",
"dev": "env-cmd -f ./config/dev.env nodemon src/index.js",
"test": "env-cmd -f ./config/test.env jest --watch"
},
"jest": {
"testEnvironment": "node",
"roots": [
"<rootDir>"
],
"modulePaths": [
"<rootDir>"
],
"moduleDirectories": [
"node_modules"
]
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@sendgrid/mail": "^7.4.6",
"bcryptjs": "^2.4.3",
"express": "^4.17.1",
"jose-node-cjs-runtime": "^3.15.5",
"mongodb": "^4.1.1",
"mongoose": "^6.0.2",
"multer": "^1.4.3",
"sharp": "^0.29.0",
"validator": "^13.6.0"
},
"devDependencies": {
"env-cmd": "^10.1.0",
"jest": "^27.1.0",
"nodemon": "^2.0.12",
"supertest": "^6.1.6"
}
}
以下是src/models/user.js
的内容:
const mongoose = require('mongoose');
const validator = require('validator');
const bcrypt = require('bcryptjs');
// library for signing jwt
const { SignJWT } = require('jose-node-cjs-runtime/jwt/sign');
// library for generating symmetric key for jwt
const { createSecretKey } = require('crypto');
// task model
const Task = require('./task');
...
src/tests/user.test.js
的内容:
const request = require('supertest');
const app = require('../src/app');
describe('user route', () => {
test('should signup a new user', async () => {
await request(app)
.post('/users')
.send({
name: '__test_name__',
email: '__test_email__',
password: '__test_password__',
})
.expect(201);
});
});
我认为你缺少 jest 的配置,可以找到它 here
主要寻找moduleirectories,
您可以添加相对路径和绝对路径。
确保包含在 roots 数组、modulePaths 数组和 node_modules moduleDirectories 数组中,除非您有充分的理由将它们排除在外。
这是 jest 配置的示例,您可以将其包含在 package.json
文件
中
"jest": {
"roots": [
"<rootDir>",
"/homeDir/yourLocalDir/path/"
],
"modulePaths": [
"<rootDir>",
"/homeDir/yourLocalDir/otherDir/path"
],
"moduleDirectories": [
"node_modules"
],
"testPathIgnorePatterns": ["/node_modules/(?!MODULE_NAME_HERE).+\.js$"]
}
我开玩笑地提出了一个 issue github 回购协议。该问题已关闭并发表评论:
The module uses exports which isn't supported yet: #9771
所以我通读了已经记录在类似问题上的评论,发现了 this 有用的评论,在 jest 原生支持此功能之前,可以将其用作解决方法。
我发现 jose-node-cjs-runtime
模块 exports
字段如下所示:
"./jwt/sign": "./dist/node/cjs/jwt/sign.js",
"./jwt/verify": "./dist/node/cjs/jwt/verify.js",
所以我更新了 package.json
中的 jest
配置如下:
"jest": {
"testEnvironment": "node",
"moduleNameMapper": {
"^jose-node-cjs-runtime/(.*)$": "jose-node-cjs-runtime/dist/node/cjs/"
}
}
在那之后运行测试我没有遇到任何问题。
您可以使用 this workaround 中的解析器。
我有一个测试仓库 jose
用于各种工具 here。
显然,如果您使用 ts-jest、ESM 测试文件或类似文件,您的设置可能会有所不同。但到那时你应该熟悉不同的笑话魔法选项了。
> jest --resolver='./temporary_resolver.js' 'jest.test.*'
PASS ./jest.test.js
✓ it works in .js (3 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.367 s, estimated 1 s
Ran all test suites matching /jest.test.*/i.
// temporary workaround while we wait for https://github.com/facebook/jest/issues/9771
const resolver = require('enhanced-resolve').create.sync({
conditionNames: ['require'],
extensions: ['.js', '.json', '.node', '.ts']
})
module.exports = function (request, options) {
return resolver(options.basedir, request)
}
const { generateSecret } = require("jose/util/generate_secret");
test('it works in .js', async () => {
expect(typeof generateSecret).toBe('function');
expect(await generateSecret('HS256')).toBeTruthy();
});
底线 - 它是关于让 jest 需要 jose 模块的 cjs 分发并使用导出映射。请注意,ESM 仍然不受本地支持,导出映射也不受支持,这两者在节点的所有 LTS 版本中都稳定了一年多。
我正在用玩笑测试我的 Node.js API。 API 是一个用于管理任务的 Express 应用程序。它具有 signup/login 功能,仅允许经过身份验证的用户使用该应用程序。它有一个用于注册新用户的端点,并且存在许多使用快速中间件通过 JWT 验证用户身份验证的端点。我安装了 jose-node-cjs-runtime@^3.15.5
包,用于 JWT 生成和验证。
如果我 运行 使用 dev
脚本 env-cmd -f ./config/dev.env nodemon src/index.js
的项目,没有问题,运行 没问题。我正在尝试使用 jest 测试文件来测试用户注册,该文件使用 superagent
包来测试端点。我正在使用测试脚本 env-cmd -f ./config/test.env jest --watch
来 运行 测试。此命令显示以下错误并且测试失败:
FAIL tests/user.test.js
● Test suite failed to run
Cannot find module 'jose-node-cjs-runtime/jwt/sign' from 'src/models/user.js'
Require stack:
src/models/user.js
src/routers/user.js
src/app.js
tests/user.test.js
3 | const bcrypt = require('bcryptjs');
4 | // library for signing jwt
> 5 | const { SignJWT } = require('jose-node-cjs-runtime/jwt/sign');
| ^
6 | // library for generating symmetric key for jwt
7 | const { createSecretKey } = require('crypto');
8 | // task model
at Resolver.resolveModule (node_modules/jest-resolve/build/resolver.js:313:11)
at Object.<anonymous> (src/models/user.js:5:21)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 3.385 s
Ran all test suites related to changed files.
我无法弄清楚为什么会导致此错误。请帮助我找到解决方案。
我使用的是 Node.js 版本 16.7.0,但遇到了这个错误。我今天升级了 Node.js 版本。我当前的 Node.js 版本是 16.9.0。升级 Node.js 版本后,我也收到此错误。以下是项目的 package.json 文件内容:
{
"name": "task-manager",
"version": "1.0.0",
"description": "",
"main": "index.js",
"engines": {
"node": ">=16.7.0"
},
"scripts": {
"start": "node src/index.js",
"dev": "env-cmd -f ./config/dev.env nodemon src/index.js",
"test": "env-cmd -f ./config/test.env jest --watch"
},
"jest": {
"testEnvironment": "node",
"roots": [
"<rootDir>"
],
"modulePaths": [
"<rootDir>"
],
"moduleDirectories": [
"node_modules"
]
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@sendgrid/mail": "^7.4.6",
"bcryptjs": "^2.4.3",
"express": "^4.17.1",
"jose-node-cjs-runtime": "^3.15.5",
"mongodb": "^4.1.1",
"mongoose": "^6.0.2",
"multer": "^1.4.3",
"sharp": "^0.29.0",
"validator": "^13.6.0"
},
"devDependencies": {
"env-cmd": "^10.1.0",
"jest": "^27.1.0",
"nodemon": "^2.0.12",
"supertest": "^6.1.6"
}
}
以下是src/models/user.js
的内容:
const mongoose = require('mongoose');
const validator = require('validator');
const bcrypt = require('bcryptjs');
// library for signing jwt
const { SignJWT } = require('jose-node-cjs-runtime/jwt/sign');
// library for generating symmetric key for jwt
const { createSecretKey } = require('crypto');
// task model
const Task = require('./task');
...
src/tests/user.test.js
的内容:
const request = require('supertest');
const app = require('../src/app');
describe('user route', () => {
test('should signup a new user', async () => {
await request(app)
.post('/users')
.send({
name: '__test_name__',
email: '__test_email__',
password: '__test_password__',
})
.expect(201);
});
});
我认为你缺少 jest 的配置,可以找到它 here
主要寻找moduleirectories, 您可以添加相对路径和绝对路径。
确保包含在 roots 数组、modulePaths 数组和 node_modules moduleDirectories 数组中,除非您有充分的理由将它们排除在外。
这是 jest 配置的示例,您可以将其包含在 package.json
文件
"jest": {
"roots": [
"<rootDir>",
"/homeDir/yourLocalDir/path/"
],
"modulePaths": [
"<rootDir>",
"/homeDir/yourLocalDir/otherDir/path"
],
"moduleDirectories": [
"node_modules"
],
"testPathIgnorePatterns": ["/node_modules/(?!MODULE_NAME_HERE).+\.js$"]
}
我开玩笑地提出了一个 issue github 回购协议。该问题已关闭并发表评论:
The module uses exports which isn't supported yet: #9771
所以我通读了已经记录在类似问题上的评论,发现了 this 有用的评论,在 jest 原生支持此功能之前,可以将其用作解决方法。
我发现 jose-node-cjs-runtime
模块 exports
字段如下所示:
"./jwt/sign": "./dist/node/cjs/jwt/sign.js",
"./jwt/verify": "./dist/node/cjs/jwt/verify.js",
所以我更新了 package.json
中的 jest
配置如下:
"jest": {
"testEnvironment": "node",
"moduleNameMapper": {
"^jose-node-cjs-runtime/(.*)$": "jose-node-cjs-runtime/dist/node/cjs/"
}
}
在那之后运行测试我没有遇到任何问题。
您可以使用 this workaround 中的解析器。
我有一个测试仓库 jose
用于各种工具 here。
显然,如果您使用 ts-jest、ESM 测试文件或类似文件,您的设置可能会有所不同。但到那时你应该熟悉不同的笑话魔法选项了。
> jest --resolver='./temporary_resolver.js' 'jest.test.*'
PASS ./jest.test.js
✓ it works in .js (3 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.367 s, estimated 1 s
Ran all test suites matching /jest.test.*/i.
// temporary workaround while we wait for https://github.com/facebook/jest/issues/9771
const resolver = require('enhanced-resolve').create.sync({
conditionNames: ['require'],
extensions: ['.js', '.json', '.node', '.ts']
})
module.exports = function (request, options) {
return resolver(options.basedir, request)
}
const { generateSecret } = require("jose/util/generate_secret");
test('it works in .js', async () => {
expect(typeof generateSecret).toBe('function');
expect(await generateSecret('HS256')).toBeTruthy();
});
底线 - 它是关于让 jest 需要 jose 模块的 cjs 分发并使用导出映射。请注意,ESM 仍然不受本地支持,导出映射也不受支持,这两者在节点的所有 LTS 版本中都稳定了一年多。