Reputation: 1780
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 }
Upvotes: 1
Views: 941
Reputation: 222750
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.
Upvotes: 2