我正在从tutorial开始学习使用NodeJS和MongoDB创建RestAPI,并从它们提供的仓库中进行了更新(此帖子有很多更新),我进一步对其进行了修改,以对我的带有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,而是用猫鼬关闭了连接,但仍然没有终止。有人能解决我的问题吗?
答案 0 :(得分:1)
如果没有正在进行的异步操作并且没有打开的处理程序(如数据库连接和服务器侦听器),则不应发生此错误。这意味着每个连接都需要在afterAll
的结尾处关闭。断开连接是异步操作,需要等待。
由于未导入start.js,因此不需要关闭服务器,Supertest request(app)
会设置服务器并自动将其关闭。
Mongo和Mongoose API支持承诺,可以使用async..await
处理。 async
不应与done
混合使用,因为这是一种反模式,通常会导致错误的控制流。
如果有默认的mongoose.connect
连接,则需要关闭:
afterAll(async () => {
await mongoose.connection.close();
});
如果存在非默认的mongoose.createConnection
连接,则也需要公开和关闭它们。
Mongo连接在这里不可用,因为它不同于Mongoose连接。 Existing Mongoose default connection can be accessed for Mongo operations就像清理。如果需要Mongo(而非Mongoose)连接,则需要明确关闭它:
afterAll(async () => {
await connection.close();
});
可以在单独的afterAll
块中完成此操作,以使失败的操作不会影响其他操作。