jest和mongoose - jest检测到打开的手柄

Rod*_*Rod 11 mongoose jestjs

所以我jest用来测试我的node.js应用程序并且测试结果很好,但是我从jest获得了关于打开句柄的消息.任何见解?

jest --detectOpenHandles

PASS src/libs/user/tests /user_model_test.js PASS src/tests /app_test.js PASS src/libs/user/tests /user_service_test.js

测试套件:3次通过,总共3次测试:14次通过,总共14次快照:0总时间:7.209s跑完所有测试套件.

Jest检测到以下4个打开的句柄可能使Jest退出:

●承诺

  2 | // we use a test database for testing
  3 | var mongoDB = 'mongodb://localhost/my_db_conn';
> 4 | mongoose.connect(mongoDB);
    |          ^
  5 | const User = require('../user_model');
  6 |
  7 | describe("User model test", () => {

  at NativeConnection.Object.<anonymous>.Connection.openUri (node_modules/mongoose/lib/connection.js:424:19)
  at Mongoose.Object.<anonymous>.Mongoose.connect (node_modules/mongoose/lib/index.js:208:15)
  at Object.<anonymous> (src/libs/user/__tests__/user_model_test.js:4:10)
Run Code Online (Sandbox Code Playgroud)

●承诺

   8 | });
   9 |
> 10 | module.exports = mongoose.model("User", UserSchema);
     |                           ^

  at Function.init (node_modules/mongoose/lib/model.js:962:16)
  at Mongoose.Object.<anonymous>.Mongoose.model (node_modules/mongoose/lib/index.js:392:11)
  at Object.<anonymous> (src/libs/user/user_model.js:10:27)
  at Object.<anonymous> (src/libs/user/__tests__/user_model_test.js:5:14)
Run Code Online (Sandbox Code Playgroud)

●承诺

   8 | });
   9 |
> 10 | module.exports = mongoose.model("User", UserSchema);
     |                           ^

  at Function.init (node_modules/mongoose/lib/model.js:962:16)
  at Mongoose.Object.<anonymous>.Mongoose.model (node_modules/mongoose/lib/index.js:392:11)
  at Object.<anonymous> (src/libs/user/user_model.js:10:27)
  at Object.<anonymous> (src/libs/user/index.js:1:41)
Run Code Online (Sandbox Code Playgroud)

●承诺

  3 | var mongoose = require('mongoose');
  4 | var mongoDB = 'mongodb://localhost/my_db_conn';
> 5 | mongoose.connect(mongoDB);
    |          ^
  6 |
  7 | describe('App test', () => {
  8 |     it('has a module', () => {

  at NativeConnection.Object.<anonymous>.Connection.openUri (node_modules/mongoose/lib/connection.js:424:19)
  at Mongoose.Object.<anonymous>.Mongoose.connect (node_modules/mongoose/lib/index.js:208:15)
  at Object.<anonymous> (src/__tests__/app_test.js:5:10)
Run Code Online (Sandbox Code Playgroud)

Fie*_*hra 10

经过几个小时的搜索 SO 和 github 问题的解决方案后,我遇到了这个 github 线程https://github.com/visionmedia/supertest/issues/520,其中提供了多种解决方案。最终对我有用的是在我的根目录中实现一个全局拆卸文件,如下所示:

\n
// test-teardown-globals.js\nmodule.exports = () => {\n  process.exit(0);\n};\n
Run Code Online (Sandbox Code Playgroud)\n

并稍微调整我的 jest.config.js

\n
// jest.config.js\nmodule.exports = {\n  preset: \'ts-jest\',\n  testEnvironment: \'node\',\n  globalTeardown: \'<rootDir>/test-teardown-globals.js\',\n};\n
Run Code Online (Sandbox Code Playgroud)\n

更新:另请注意@SimonSimCity 的评论,该解决方案需要一些权衡。考虑通过断开猫鼬连接来使用 \xc3\x96zg\xc3\xbcr Atmaca\ 的答案。

\n

  • **注意:** 通过使用此功能,即使测试失败,您的进程也将始终将“0”作为返回代码!通常该命令会在出错时返回“1”。背景:大多数系统依靠返回代码来确定命令是否成功运行。 (6认同)
  • 神奇!你的回答让我免于几个小时的疯狂调试和搜索修复,直到 Google 第 3 页。作品!! (2认同)
  • @Fiehra 正是如此。我也会避免在本地使用它。我经历了惨痛的教训,在这次事件发生后需要花费大量时间才能再次获得对 CI 管道和流程的信任...... (2认同)

小智 8

测试后您的猫鼬连接似乎仍保持打开状态,请尝试以下操作之一:

  1. 测试后关闭服务器实例。

    const server = require('./app'); //server instance    
    server.close(); //put in afterAll or afterEach depending on your test
    
    Run Code Online (Sandbox Code Playgroud)
  2. 所有测试后关闭数据库连接。

    afterAll(()=>{ mongoose.connection.close();});
    
    Run Code Online (Sandbox Code Playgroud)
  3. 用 async/await 包装你的猫鼬连接。

    async function(){
       await mongoose.connect(mongoDB);
    };
    
    Run Code Online (Sandbox Code Playgroud)

尝试一种或多种组合。这些是我的解决方案,因为我无法真正看到您的代码。

  • 添加 `mongoose.connection.close()` 后,我仍然收到 mongoose.connect 的 openHandles 错误 (3认同)

小智 3

它与model.init返回承诺的函数有关。快速修复方法是skipInit在创建模型时传递标志,如下所示:

const User = mongoose.model("users", userSchema, "users", true)

skipInit是该函数中的第四个参数

但在这种情况下,它不会初始化模型的索引,因此最好根据process.env.NODE_ENV

const skipInit = process.env.NODE_ENV === "test" const User = mongoose.model("users", userSchema, "users", skipInit)

  • @Alex我使用了你的答案并且它有效 - 它可以防止开玩笑地抱怨公开承诺。不过,我不确定它是否还有其他问题。在我的实时数据库中,它正确地抱怨重复的电子邮件,因为它是一个独特的字段。在我通过mockgoose测试数据库中,它没有错误。我只能假设是因为设置了skipInit = false,但我正在继续调查 (2认同)