Geoffrey Wiseman
Geoffrey Wiseman

Reputation: 5637

Holding Supertest Until API Initialized

I have a mocha test using Supertest of an express API that uses MongoDB. MongoDB is running, but I'm currently having Supertest require and use the express API rather than starting it up separately (I'd prefer this approach):

var request = require( 'supertest' );
var chai = require( 'chai' );
var api = require( '../../server/api.js' );

chai.should();

describe( "/api/lists", function() {
    it( "should be loaded", function() {
        api.should.exist;
    } );
    it( "should respond with status 200 ", function( done ) {
        request( api )
            .get( '/api/lists' )
            .expect( 200, done );
  } );
} );

When the test runs, it fails:

TypeError: Cannot call method 'collection' of undefined
    at app.get.listId (/my/path/api.js:63:5)

I suspect that supertest is running the test on my API before the MongoDB connection has been established. What's the right way to get it to hold off until my API is fully initialized?

I imagine that if I run the test through Grunt after starting up express, it'd be fine, but since Supertest can start up express on my behalf, I was hoping to start with that approach.

Upvotes: 1

Views: 988

Answers (3)

Aleksei Zabrodskii
Aleksei Zabrodskii

Reputation: 2228

Since Mongoose buffers queries until connection is available, following setup should be enough:

describe('test', function () {
  before(mongoose.connect.bind(mongoose, connectionString));

  // do your tests...
);

But from what I can tell by error message, it looks like you are failing to initialize your models. What's actual code at api.js:63:5?

Upvotes: 0

Rahat Mahbub
Rahat Mahbub

Reputation: 2987

You can do the following:

describe( "/api/lists", function() {
    before(function(done) {
        mongoose.connect(config.db.mongodb);
        done();
     });
     it( "should be loaded", function() {
         ....

Upvotes: 1

Bill Poitras
Bill Poitras

Reputation: 667

I run my tests using Mockgoose, an in memory wrapper for mongoose. I suspect there is no measurable connection time. I execute my tests with a test only environment which doesn't specify my url configuration property. My mongoose initialization looks like this:

    if (url) {
    config.logger.info('Attempting Mongoose Connection: ', url);
    db.connection = connection = mongoose.createConnection(url, {
        server: {
            keepAlive: 1, auto_reconnect: true
        },
        user: db.username,
        pass: db.password
    });
} else {
    config.logger.info('No database specified, using Mockgoose in memory database');
    config.mockgoose = require('mockgoose')(mongoose);
}

In my tests:

    describe('Mockgoose tests', function() {
    beforeEach(function(done) {
        config.mockgoose.reset(); // Start with empty database
        // Other database initialization code here
        done();
    }

    it('Mockgoose test', function(done) {
        ...
    }
}

This allows me to load datasets or single objects into the database. Since mockgoose is in memory, its very fast. The downside is not all mongoose operations are supported by mockgoose. I've had issues with queries which combine $or and $elemMatch.

Upvotes: 0

Related Questions