Reputation: 11064
I'm new to unit testing node and mongodb.... I am trying to test getUsername()
but I get TypeError: user.find is not a function
. I believe this might be a race condition where the db-init.js
script hasn't established a connection in time with the database before the first it
block runs.
Just to be clear, there are no issues with the code outside of the test. Outside of the test, everything works as it should.
Any suggestions, please?
test:
var api = require('../app/js/api');
var httpMocks = require('node-mocks-http');
var req;
var res;
describe('db calls', function() {
beforeEach(function() {
api.initDBcursor();
req = httpMocks.createRequest({
params: { username: "foo" }
});
res = httpMocks.createResponse();
});
it('should get username',
function(done) {
api.getUsername(req, res);
console.log(res);
});
});
api.js
var mongo = require('../data/db-init');
var user;
function initDBcursor() {
user = mongo.collections.user;
}
function getUsername(req, res) {
console.log(user);
var document = user.find(req.params.username); //HERE IS WHERE IT ERRORS
_returnApi(document, res);
}
users.js
User.prototype.find = function(user) {
return this.collection.find(user).limit(1).next();
};
db-init.js
var MongoClient = require('mongodb').MongoClient;
var User = require('./models/users');
var db;
var collections = {
user: false //THIS SHOULD HAVE A VALUE FROM initCollections() BEFORE
//BEFORE THE FIRST IT BLOCK RUNS
};
function connect() {
var dbURI = 'mongodb://web-app:web-app@localhost/web-app';
return MongoClient.connect(dbURI)
.then(function(_db) {
db = _db;
console.log(colors
.bold('MongoDB default connection open to ' + dbURI));
initCollections();
})
.catch(function(err) {
console.log(colors
.red(err));
});
}
function initCollections() {
collections.user = new User(db);
}
Upvotes: 0
Views: 1368
Reputation: 11064
I got it working. After taking a break and clearing my mind, I realized I wasn't starting the db.
Thank you for the suggestions, but it is important to me not to change the original code. By a self given rule, I never change the code base to fit the test.
Also, after google searching and reading mocha docs on async, I found a way to make it wait in mocha. This is a quick and dirty solution that I wrote where it's working....
var api = require('../app/js/api');
var yo = require('../app/data/db-init');
var httpMocks = require('node-mocks-http');
describe('db calls', function() {
beforeEach(function(done) {
this.timeout(0)
yo.connect().then(function() {
api.initDBcursor();
});
setTimeout(function() {
done()
}, 5000);
req = httpMocks.createRequest({
params: { username: "foo" }
});
res = httpMocks.createResponse();
});
UPDATE After trying ways...I have found that using SuperTest and/or Chai Http will handle the async handling for you, reducing the code base of test. However, on the downside you will actually have a node server running which will be slightly less quick.
Upvotes: 0
Reputation: 48376
Try to do it through done
in the before
function as below, without creating connection in beforeEach
, which will build new connection for every test case. Here are some sample codes.
test.js
before(function(done) {
api.initDBcursor(done);
});
api.js
function initDBcursor(cb) {
//user = mongo.collections.user;
mongo.connect(cb);
}
db-init.js
exports.connect = function (cb) {
var dbURI = 'mongodb://web-app:web-app@localhost/web-app';
return MongoClient.connect(dbURI)
.then(function(_db) {
db = _db;
console.log(colors
.bold('MongoDB default connection open to ' + dbURI));
initCollections();
cb && cb();
})
.catch(function(err) {
console.log(colors
.red(err));
cb && cb(err);
});
}
Upvotes: 1