mongoose.connection.collections.collection.drop() throws error every other time mongoose.connection.collections.collection.drop() throws error every other time mongodb mongodb

mongoose.connection.collections.collection.drop() throws error every other time


I don't know why mongoose.connection.collections.<collection>.drop() randomly throws errors, but there is a simple way to remove all the documents in Mongoose, which works just fine for resetting the collection before tests:

beforeAll(async () => {  await User.remove({})})

Works every time.


I was having a similar issue while trying to drop the database in the beginning of the tests and populating the database right after. In the first run, collections would be created; in the next one, I would get an error of 'database is in the process of being dropped.'; ...and it was alternating like this.

I was also using an "in memory" Mongodb, running $ run-rs -v 4.0.0 -s (https://www.npmjs.com/package/run-rs) in a separate terminal window before running my Mocha tests. Also, I have Mongoose 5.2.0 and Mocha 5.1.1 here.

I've found out that Mongoose not necessarily executes the the drop commands immediately. Instead, it will schedule them for when the connection is up.

So, there can be a race condition in which the promise of the drop command is resolved and you move on in the code until reaching the instruction for creating your collections... but the drop command didn't finish running yet, and you'll get the error for the creation the new collections. The drop finish running and for the next time you run your test, your database (or collection) is already dropped, and hence you'll be able to insert the new collections again.

So, this is how I've solved...

Run in the before hook:

test.dropDb = function(done) {    this.timeout(0)    let database = your_MongoDB_URI    mongoose.connect(database, function (err) {        if (err) throw err;        mongoose.connection.db.dropDatabase(function(err, result){            console.log('database dropping was scheduled');        });    })    mongoose.connection.on('connected', function() {        setTimeout(function(){ done() }, 3000);    });}

Run in an nested before hook

test.createDb = function(done) {    this.timeout(0)    let createDb = require('./create-db.js')    createDb() // here I call all my MyCollections.insertMany(myData)...    .then( function() {        done()    })    .catch( function(err) {        assert( null == err)    });}

Run in the after hook

test.afterAll = function(done) {        mongoose.connection.close()    .then( function() {        done()    })}

I don't know why I had to explicitly close the connection in the after hook. I guess it has something to do with the way run-rs is programmed, but I didn't look into it. I just know that, in my case, closing the connection after the test was mandatory to get the expected behavior.