Mau*_*ani 13 node.js express supertest jestjs
我开始使用 Jest 和 Supertest(针对端点)测试我的应用程序。测试工作顺利,但Jest 在运行测试后检测到 2 个打开的句柄,这会阻止 Jest 干净退出。
\n这个打开的句柄是由我的测试文件中调用的外部异步函数生成的。我正在使用外部函数从 Auth0 API 请求 JWT 令牌;但对 Auth0 的请求还在其响应中提供了传递端点中间件的关键信息(有关此的更多信息如下)。这里要记住两件事:
\nuser具有关键信息的对象。Auth0 将此对象设置在主体响应之外的同一级别,但不在其中。该信息是传递端点中间件的关键。getToken测试文件中的该函数(称为 )生成的。import app from "../app";\nimport mongoose from "mongoose";\nimport supertest from "supertest";\nimport { getToken } from "../helpers";\nimport dotenv from "dotenv";\nimport * as config from "../config";\n\ndotenv.config();\n\nconst api = supertest(app);\n\nlet authToken: any;\nlet db: any;\n\nbeforeAll(async() => {\n try {\n mongoose.connect(config.MONGODB_URI, {\n useNewUrlParser: true,\n useUnifiedTopology: true,\n useCreateIndex: true,\n });\n db = mongoose.connection;\n db.on("error", console.error.bind(console, "Console Error:"));\n db.once("open", () =>\n console.log(`App connected to "${db.name}" database`)\n );\n authToken = await getToken()\n } catch (err) {\n return err\n }\n});\n\ndescribe("GET /interview/:idCandidate", () => {\n test("With auth0 and read permissions", async () => {\n await api\n .get("/interview/1")\n .set("Authorization", "Bearer " + authToken)\n .expect(200)\n });\n});\n\nafterAll(async () => {\n try {\n await db.close();\n } catch (err) {\n return err;\n }\n});\nRun Code Online (Sandbox Code Playgroud)\ngetToken向 Auth0 API 请求信息的外部函数从外部模块导入的函数getToken如下:
import axios from 'axios'\n\nvar options = {\n url: //url goes here,\n form:\n {\n // form object goes here\n },\n json: true\n };\n \n const getToken = async () => {\n try {\n const tokenRequest = await axios.post(options.url, options.form)\n return tokenRequest.data.access_token\n } catch (err){\n return err\n }\n } \n\n\nexport default getToken;\nRun Code Online (Sandbox Code Playgroud)\n一旦运行我的测试,它们就会按预期运行,直到 Jest 的--detectOpenHandles配置检测到以下两个打开的句柄:
Jest has detected the following 2 open handles potentially keeping Jest from exiting:\n\n \xe2\x97\x8f TLSWRAP\n\n 60 | case 0:\n 61 | _a.trys.push([0, 2, , 3]);\n > 62 | return [4 /*yield*/, axios_1.default.post(options.url, options.form)\n | ^\n 63 | ]; \n 64 | case 1: \n\n at RedirectableRequest.Object.<anonymous>.RedirectableRequest._performRequest (node_modules/follow-redirects/index.js:265:24)\n at new RedirectableRequest (node_modules/follow-redirects/index.js:61:8)\n at Object.request (node_modules/follow-redirects/index.js:456:14)\n at dispatchHttpRequest (node_modules/axios/lib/adapters/http.js:202:25)\n at httpAdapter (node_modules/axios/lib/adapters/http.js:46:10)\n at dispatchRequest (node_modules/axios/lib/core/dispatchRequest.js:53:10)\n at Axios.request (node_modules/axios/lib/core/Axios.js:108:15)\n at Axios.<computed> [as post] (node_modules/axios/lib/core/Axios.js:140:17)\n at Function.post (node_modules/axios/lib/helpers/bind.js:9:15)\n at call (dist/helpers/getToken.js:62:54)\n at step (dist/helpers/getToken.js:33:23)\n at Object.next (dist/helpers/getToken.js:14:53)\n at dist/helpers/getToken.js:8:71\n at __awaiter (dist/helpers/getToken.js:4:12)\n at Object.token (dist/helpers/getToken.js:56:34)\n at call (dist/test/api.test.js:87:48)\n at step (dist/test/api.test.js:52:23)\n at Object.next (dist/test/api.test.js:33:53)\n at dist/test/api.test.js:27:71\n at __awaiter (dist/test/api.test.js:23:12)\n at dist/test/api.test.js:72:32\n\n\n \xe2\x97\x8f TLSWRAP\n\n 141 | switch (_a.label) {\n 142 | case 0: return [4 /*yield*/, api\n > 143 | .get("/interview/1")\n | ^\n 144 | .set("Authorization", "Bearer " + authToken)\n 145 | .expect(200)];\n 146 | case 1:\n\n at Test.Object.<anonymous>.Test.serverAddress (node_modules/supertest/lib/test.js:61:33)\n at new Test (node_modules/supertest/lib/test.js:38:12)\n at Object.get (node_modules/supertest/index.js:27:14)\n at call (dist/test/api.test.js:143:26)\n at step (dist/test/api.test.js:52:23)\n at Object.next (dist/test/api.test.js:33:53)\n at dist/test/api.test.js:27:71\n at __awaiter (dist/test/api.test.js:23:12)\n at Object.<anonymous> (dist/test/api.test.js:139:70)\nRun Code Online (Sandbox Code Playgroud)\n我确信错误来自这个getToken异步函数。
您可能想知道为什么我不嘲笑该函数,正如我之前所说,当 Auth0 使用令牌响应(顺便说一下,它经常刷新)时,它还会响应有关用户的信息,并且该信息超出了response.body. 事实上,它与body. 所以,如果我想模拟这个函数,我必须在一侧设置带有不记名令牌的授权标头(这很容易用 Supertest 完成),user在另一侧设置 Auth0 提供的信息;但这最后一步是不可能的(至少据我所知;否则,如何user在与正文相同的层次结构级别而不是在其中设置信息属性?)
我尝试为测试添加更长的超时beforeAll();我尝试添加done回调而不是async/await在内部使用beforeAll()和其他一些不太重要的事情,但它们都没有解决打开句柄问题。事实上,我已经检查了对 Auth0 API 的请求过程是否在响应后关闭,并且实际上该连接关闭,但在运行测试后我仍然收到打开句柄错误。
任何想法将不胜感激!
\n今天我也遇到了类似的问题,未能找到明确的解决方案,但找到了解决方法。解决方法(由alfreema发布)是在调用之前添加以下行axios.post:
await process.nextTick(() => {});
Run Code Online (Sandbox Code Playgroud)
这似乎让 Axios 完成了它的内务处理,并准备好跟踪随后打开的新连接。这只是我的猜测,我希望其他人能够对此有更多的了解并提供适当的解决方案。
| 归档时间: |
|
| 查看次数: |
2722 次 |
| 最近记录: |