How to test own mongodb wrapper

Problem

I have written own thin mongodb wrapper for Node.js to eliminate code repetition.

However, I am having problems with asynchronous unit tests run with Mocha and Should.

What happens is that any thrown exception by Should library is being caught by MongoDB driver instead of Mocha. I.e., neither Mocha catches the error, nor done() function gets called. As a consequence, Mocha prints out an error Error: timeout of 2000ms exceeded.

Snippet of wrapper module db.js

var mongodb = require('mongodb').MongoClient;

exports.getCollection = function(name, callback) {
    mongodb.connect(dbConfig.dbURI, {auto_reconnect: true}, function(err, db) {
        if (err)
            return callback(err, null);

        db.collection(name, {strict: true}, callback);
    });
};

Mocha test.js

var should = require('should');
var db     = require('./db.js');

describe('Collections', function() {
    it.only('should retrieve user collection', function(done) {
        db.getCollection('user', function(err, coll) {
            should.not.exist(err);
            coll.should.be.a('object');
            // HERE goes an assertion ERROR
            coll.collectionName.should.equal('user123');

            done();
        });
    });
});

The same behaviour can be simulated by this simple test.js

var should = require('should');

var obj = {
    call: function(callback) {
        try {
            console.log('Running callback(null);');
            return callback(null);
        }
        catch(e) {
            console.log('Catched an error:', e);
        }
    }
};

describe('Test', function() {
    it('should catch an error', function(done) {
        obj.call(function(err) {
            should.exist(err);
            done();
        });
    });
});

Is there any way to workaround the issue? There must be a way to test such code.

Problem courtesy of: Pavel Lobodinský

Solution

Just by an accidental luck I spotted a GitHub fork dealing with a different problem, but the code lead me to realise I can use a simple trick to make Mocha to catch the assert exceptions:

describe('Test', function() {
    it('should catch an error', function(done) {
        obj.call(function(err) {
            try {
                should.exist(err);
                done();
            } catch (err) {
                done(err);
            }
        });
    });
});

I.e. wrapping the should calls into try/catch block and calling done(err) in the catch section does exactly what is expected :

  1. Test passes successfully if no assertion error occurs
  2. Test fails in case of assertion error thanks to done() function accepting an error argument
Solution courtesy of: Pavel Lobodinský

Discussion

There is currently no discussion for this recipe.

This recipe can be found in it's original form on Stack Over Flow.