Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
114
rated 0 times [  120] [ 6]  / answers: 1 / hits: 20157  / 9 Years ago, sun, february 15, 2015, 12:00:00

I'm writing a unit test for my simple Node.js application using Mocha. The application has a class which connects to a Mongo database, fetch the record, and store the formulated record as a field. Simply, the class looks like this:



SampleClass.prototype.record = []; // Store the loaded record
SampleClass.prototype.init = function(db){
var self = this;
self.db = mongoose.connection; // Say we already have mongoose object initialized
self.db.once('open',function(){
/* schema & model definitions go here */
var DataModel = mongoose.model( /* foobar */);
DataModel.findOne(function(err,record){
/* error handling goes here */

self.record = record; // Here we fetch & store the data
});
});
}


As seen from the snippet above, once the SampleClass.init() is called, the Sample.record will not instantly get populated from the database. The data is asynchronously populated once the event 'open' is fired. Thus, there will possibly be a delay after SampleClass.init() until the Sample.record is populated.



So it comes into a complication when I write a Mocha test like this:



var testSampleClass = new SampleClass();

describe('SampleClass init test',function(){
testSampleClass.init('mydb');
it('should have 1 record read from mydb',function(){
assert.equal(testSampleClass.record.length,1);
});
});


The assertion above will always fail because testSampleClass.record will not get populated straightaway after init. It needs a gap of time to load the data.



How can I delay the test case so it starts a few seconds or more after testSampleClass.init is called? Is it also possible to trigger the test case right after an event of my class is fired? Otherwise, this simple case will always fail which I know this is not correct at all.


More From » node.js

 Answers
10

Use before() or beforeEach hooks (see here and here). They take done callback as argument, which you must call when some asynchronous staff will be completed. So you test should looks like:



describe('SampleClass init test',function(){
before(function(done) {
testSampleClass.init('mydb', done);
});
it('should have 1 record read from mydb',function(){
assert.equal(testSampleClass.record.length,1);
});
});


And your init method:



SampleClass.prototype.record = []; // Store the loaded record
SampleClass.prototype.init = function(db, callback){
var self = this;
self.db = mongoose.connection; // Say we already have mongoose object initialized
self.db.once('open',function(){
/* schema & model definitions go here */
var DataModel = mongoose.model( /* foobar */);
DataModel.findOne(function(err,record){
/* error handling goes here */

self.record = record; // Here we fetch & store the data
callback();
});
});
}

[#67816] Friday, February 13, 2015, 9 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
reed

Total Points: 725
Total Questions: 85
Total Answers: 89

Location: Singapore
Member since Sat, Jul 25, 2020
4 Years ago
;