首页 > 解决方案 > 在 mongoose 和 supertest 的测试运行完成后,Jest 没有退出一秒钟

问题描述

我正在学习使用本教程中的 NodeJS 和 MongoDB 创建 RestAPI ,并且从他们提供的 repo [帖子中有很多更新],我进一步修改它以使用 Jest 和 SuperTest 对我的 Mongo 服务器进行单元测试.

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

将监听逻辑移至 a start.js,同时package.json将其设为主文件

开始.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};

包.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.

已经尝试了这里的大多数建议,例如 runInBand,而是关闭与 mongoose 的连接,但它仍然没有终止。有人能解决我的问题吗?

标签: node.jsmongodbasync-awaitjestjssupertest

解决方案


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

由于没有导入start.js,所以不需要关闭服务器,Supertestrequest(app)设置了一个服务器并自动关闭它。

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

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

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

如果有非默认mongoose.createConnection连接,它们也需要暴露和关闭。

Mongo 连接在这里不可用,因为它与 Mongoose 连接不同。可以访问现有的 Mongoose 默认连接以进行清理等 Mongo 操作。如果需要 Mongo(不是 Mongoose)连接,则需要显式关闭它:

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

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


推荐阅读