问题
I'm using something akin to How to properly reuse connection to Mongodb across NodeJs application and modules to keep my mongoDB Connection open.
This requires all the code to go into a MongoDB.connectDB(async (err) => {...}
Block.
How would I use this when writing Tests with Mocha.
Do I have to use a separate Connection for every test? Like this?
const MongoDB = require('../src/mongoUtil') // providing access to the mongo database
var events = require('../src/events') // containing all my database Functions
describe('events.js', function () {
describe('addEvent()', function () {
it('should return the event, when added succesfully', async function () {
await MongoDB.connectDB(async (err) => {
if (err) throw err
const database = MongoDB.getDB()
const eventsCollection = database.db().collection('events')
const event = {
name: 'test Event',
members: []
}
const result = await events.addEvent(eventsCollection, event)
MongoDB.disconnectDB()
if (result.name !== event.name) {
return new Error('TODO')
}
})
})
})
})
For this example to work properly I probably also have to manually set the test to done, if I understood the mocha website correctly?
Can I have just one connection?
mongoUtil.js
const MongoClient = require('mongodb').MongoClient
const uri = 'mongodb://localhost:27017/testing'
let _db
const connectDB = async (callback) => {
try {
MongoClient.connect(uri, { useNewUrlParser: true }, (err, db) => {
_db = db
return callback(err)
})
} catch (e) {
throw e
}
}
const getDB = () => _db
const disconnectDB = () => _db.close()
module.exports = { connectDB, getDB, disconnectDB }
events.js
const addEvent = async (collection, event) => {
try {
const exists = await collection.findOne({ 'name': event.name })
if (exists) {
return false
} else {
const results = await collection.insertOne(event)
return results.ops[0]
}
} catch (e) {
throw e
}
}
module.exports = { addEvent }
回答1:
You don't need to put everything inside MongoDB.connectDB({...})
. This is called callback hell which should be avoided when possible. mongoUtil
is inconvenient wrapper that doesn't make MongoDB API simpler or easier to use.
await MongoDB.connectDB(async (err) => { ...
is a mistake. Putting async
function as a callback is not enough and will result in improper control flow.
MongoClient.connect
uses error-first callbacks, so it can be used with done
to pass errors to test suite:
let db;
beforeEach(done => {
MongoClient.connect(uri, { useNewUrlParser: true }, (err, _db) => {
db = _db;
done(err);
});
});
connectDB
incorrectly promisifies MongoClient.connect
. There's no need for one-time callbacks when promises and async..await
are in use. It could be:
const connectDB = () => {
return new Promise((resolve, reject) => {
MongoClient.connect(uri, { useNewUrlParser: true }, (err, db) => {
if (err) reject(err);
else resolve(db);
});
});
};
But the fact is that mongodb
supports promises natively when callback argument is omitted. mongoUtil
needs only one helper function, connectDB
:
const connectDB = () => MongoClient.connect(uri, { useNewUrlParser: true });
Which can be used with Mocha seamlessly since it supports promises:
let db;
beforeEach(async () => {
db = await connectDB();
});
afterEach(() => db.close());
close
is asynchronous and returns a promise, too.
来源:https://stackoverflow.com/questions/51993399/keep-mongodb-connection-open-while-running-tests-using-mocha-framework