在使用 mongoose 和 supertest 完成测试 运行 后,Jest 没有退出一秒钟

Jest did not exit one second after the test run has completed with mongoose and supertest

我正在学习使用 NodeJS 和 MongoDB 从这个 tutorial 和他们提供的回购中创建 RestAPI [其中有很多来自 post],我进一步修改它以使用 Jest 和 SuperTest 对我的 Mongo 服务器进行单元测试。

在添加我的之前我对回购所做的主要更改是:

将监听逻辑移动到 start.js,而在 package.json 中将其设为主文件

start.js

const { app } = require("./index");

// Setup server port
var port = process.env.PORT || 8080;

app.listen(port, function () {
    console.log("Running RestHub on port " + port);
});

module.exports = {app};

在移动逻辑后通过导出将应用包装在 index.js 中。

index.js

app.use('/api', apiRoutes);
// Launch app to listen to specified port
// app.listen(port, function () {
//     console.log("Running RestHub on port " + port);
// });

module.exports = {app};

package.json

{
  "name": "resthub2",
  "version": "2.0.0",
  "description": "A Node App demonstrating simple RESTFul API implementation",
  "main": "start.js",
  "scripts": {
    "test": "jest",
    "start": "node start.js"
  },
  "keywords": [
    "API",
    "resful",
    "json",
    "node",
    "mongodb",
    "express"
  ],
  "author": "David Inyang-Etoh",
  "license": "ISC",
  "dependencies": {
    "@shelf/jest-mongodb": "^1.2.3",
    "body-parser": "^1.19.0",
    "express": "^4.17.1",
    "jest": "^26.4.2",
    "mongoose": "^5.6.4",
    "supertest": "^5.0.0"
  }
}

我按照特殊说明将 Jest 和 SuperTest 连接到 MongoDB 并添加了这两个文件。

jest.config.js

module.exports = {
  "preset": "@shelf/jest-mongodb"
};

contactController.test.js

const {MongoClient} = require('mongodb');
const {app} = require('./index'); // Link to your server file

const supertest = require('supertest');
const request = supertest(app);
const mongoose = require("mongoose");
const Contact = require("./contactModel");



describe('insert', () => {

  let connection;
  let db;

  beforeAll(async (done) => {
    connection = await MongoClient.connect(global.__MONGO_URI__, {
      useNewUrlParser: true,
    });
    db = await connection.db(global.__MONGO_DB_NAME__);
    Contact.deleteMany({}, (err) => {
      done();
    });

  });

  afterAll((done) => {

    console.log("After all?");
    // await connection.close();
    mongoose.connection.close();
    // await db.close();
    done();
  });

  it('should insert a doc into collection', async (done) => {

    try {
      const item = {};
      item["name"] = "John 3";
      item["email"] = "john@example.org";
      item["phone"] = "12345678";
      item["gender"] = "Male";

      const response2 = await request
        .post('/api/contacts')
        .send(item);
      console.log(response2.status);
      console.log("Response2 done");


      const response = await request.get("/api/contacts");
      console.log(`Weird response status is ${response.status}`);
      expect(response.status).toBe(200);
      expect(response.body.data.length).toBe(1);

      done();

    } catch (error) {
      console.log(error);
    }
  }, 30000);
});

然而,我的测试没有终止,即使我会通过所有(只有 1),并给我以下消息

Jest did not exit one second after the test run has completed. This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with `--detectOpenHandles` to troubleshoot this issue.

已经尝试了here中的大部分建议,比如runInBand,改为用mongoose关闭连接,但还是没有终止。有人能解决我的问题吗?

如果没有正在进行的异步操作并且没有打开处理程序(如数据库连接和服务器侦听器),则不应发生此错误。这意味着每个连接都需要在 afterAll 结束时关闭。关闭连接是异步操作,需要等待。

由于start.js没有导入,所以不需要关闭服务器,超测request(app)建立一个服务器,自动关闭

Mongo 和 Mongoose API 支持 promises 并且可以用 async..await 处理。 async 不应与 done 混合使用,因为这是一种反模式,通常会导致不正确的控制流。

如果有默认的mongoose.connect连接,需要关闭:

  afterAll(async () => {
    await mongoose.connection.close();
  });

如果有non-defaultmongoose.createConnection个连接,也需要暴露和关闭。

Mongo 连接在这里不可用,因为它不同于 Mongoose 连接。 Existing Mongoose default connection can be accessed for Mongo operations 喜欢清理。如果需要 Mongo(不是 Mongoose)连接,则需要明确关闭它:

  afterAll(async () => {
    await connection.close();
  });

这可以在单独的 afterAll 块中完成,以使失败的操作不影响其他操作。