0

I have written this code in express.js and mongoose

routes.js

var mongoose = require('mongoose'),
    logger = require('../logger');

mongoose.connection.on('error', function(){
    logger.info('Mongoose connection error' + error);
});

exports.getitems = function(req, res) {
    mongoose.connect('mongodb://localhost/abhitest', {auto_reconnect: true, native_parser: true}, function(err){        
        if (err) logger.error("Error " + err);
    });
    var Schema = mongoose.Schema;
    var User = new Schema({
        username : {type: String, required: true},
        email : {type: String, required: true}
    }, {collection: 'User'});

    var UserModel = mongoose.model('User', User, 'User');   
    UserModel.find({}, function(err, users){
        if (!err) {
            logger.info('found ' + users);
            res.json(200, users);
        } else {
            logger.error(err);
            res.json(404, 'did not find anything');
        }
    });
};

app.js

var mongoose = require('mongoose'),
    express = require('express'),
    app = express(),
    routes = require('./routes'),
    http = require('http');

app.get('/', routes.getitems);
http.createServer(app).listen(3000);
module.exports = app;

When I execute this from the browser. I can see that it returns results correctly from my mongo db.

But when I write this mocha test case for the same code

var app = require('../app'),
    request = require('supertest'),
    assert = require('assert'),
    _ = require('underscore');

describe('when the test runs', function() {
    it ('should insert 3 records in mongo db', function(done){
        request(app)
        .get('/')       
        .expect('Content-Type', /json/)
        .expect(200)
        .end(function(err, res){
            if (err) console.log(err);          
            else {
                console.log(res.text);
                var items = JSON.parse(res.text);
                for(var i = 0; i < items.length; i++) {
                    var item = items[i];
                    assert(_.has(item, 'username'));
                    assert(_.has(item, 'email'));
                    console.log(item.username);
                    console.log(item.email);
                }
            }
        });
        done();
    });
});

The test case output is just

1 passing (18ms)

So I am very sure that it doesn't even go inside the end method and it doesn't print anything inside the end method.

I can see that the call goes to the server but it never establishes the connection with mongo. it just hangs as readyState of 2.

So somehow when the test is executing via mocha... it never connects to mongo and is hung on connecting. but when the code is executed via npm start... everything works fine.

What is going wrong with mocha test case?

Knows Not Much
  • 30,395
  • 60
  • 197
  • 373
  • 1
    Why don't you try to reproduce the problem on a smaller scale? First, it will help you understand (and most likely fix) this yourself. Second, 90% of the people here will just look at the length of code you posted and navigate away. There's a lot of code there that is completely unrelated to the issue. It's just noise in your post. – salezica Jun 07 '14 at 01:37
  • 1
    you are calling done() right after invoking your request, mocha will interpret that as a successfuly finished test you need to invoke done() inside your end function. – Dayan Moreno Leon Jun 07 '14 at 02:49

1 Answers1

1

Your done() call needs to be made from within the request callback:

describe('when the test runs', function() {
    it ('should insert 3 records in mongo db', function(done){
        request(app)
        .get('/')       
        .expect('Content-Type', /json/)
        .expect(200)
        .end(function(err, res){
            if (err) console.log(err);          
            else {
                console.log(res.text);
                var items = JSON.parse(res.text);
                for(var i = 0; i < items.length; i++) {
                    var item = items[i];
                    assert(_.has(item, 'username'));
                    assert(_.has(item, 'email'));
                    console.log(item.username);
                    console.log(item.email);
                }
            }
            return done();
        });
    });
});

As it is currently, you call done() before your request is finished.

Jorge Aranda
  • 2,050
  • 2
  • 20
  • 29