Reputation: 4264
Mongo Novice here. I am trying to connect a unit test my mongo db collections using Mocha, Chai. But every time I run the test, the connection seems to time out. I have increased timeout
in mocha.opts
to 50K ms but still the connection seems to time out. I'm unable to get the reason why?
Here is my code
use strict';
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const chai = require('chai');
const expect = chai.expect;
/**
*
* Create a new schema that accepts a firstname and lastname and employee id
*/
const testSchema = new Schema({
firstname : {type: String,required:true},
lastname : {type: String, required:true},
id : {type : Number, required : true}
});
/**
*
* Create a new collection name employee_details
*/
const employee_details = mongoose.model('employee_details',testSchema);
describe('Create a connection with the database',()=>{
before((done)=>{
mongoose.connect('mongodb://127.0.0.1:27017/new_demo');
//I tried changing the url to mongodb://localhost/new_demo but it didn't work
const db = mongoose.connection;
db.on('error',console.error.bind(console,'Error connecting to DB'));
db.once('open',()=>{
console.log('Connected to new_demo db');
done();
});
});
});
describe('Test Database function',()=>{
//Save something with value Mike Stevens, 19981
it('saves a new record',(done)=>{
var first_record = employee_details({
firstname : 'Mike',
lastname : 'Stevens',
id : 19981
});
first_record.save(done);
});
after((done)=>{
mongoose.connection.db.dropDatabase(()=>{
mongoose.connection.close(done);
});
});
});
Things I have tried so far
mongodb://localhost/new_demo
and mongodb://localhost:27017/new_demo
mongod
in shell and then tried running the mocha testThe error message is
Error: Timeout of 50000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/ab/ab/abcd/api-testing/mongo-testing/my-mongo-tests/test/create_connection.js)
As per the error message, the done
should be called, which is done in the code. Then why this error?
Edit 1 : Full error message
Test Database function
1) saves a new record
2) "after all" hook
0 passing (50s)
2 failing
1) Test Database function
saves a new record:
Error: Timeout of 50000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/ab/ab/abcd/api-testing/mongo-testing/my-mongo-tests/test/create_connection.js)
2) Test Database function
"after all" hook:
TypeError: Cannot read property 'dropDatabase' of undefined
at Context.after (test/create_connection.js:56:34)
Upvotes: 1
Views: 1279
Reputation: 2899
A mocha test case is no different than normal JS code, thus it will follow the scope isolation and flow of JS code. I have tried to fix the test case to allow variable access in various test cases and before/after hooks.
Please note that I have not executed the actual test case and you may need to modify the code below to make it run successfully for you
'use strict';
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const chai = require('chai');
const expect = chai.expect;
/**
*
* Create a new schema that accepts a firstname and lastname and employee id
*/
const testSchema = new Schema({
firstname: { type: String, required: true },
lastname: { type: String, required: true },
id: { type: Number, required: true }
});
/**
*
* Create a new collection name employee_details
*/
const employee_details = mongoose.model('employee_details', testSchema);
/**
* Decalre the db const in this(global) context so this variable is visible by all test cases
*/
const db;
// describe('Create a connection with the database', () => {
// // Seems redundet to something
// // Also the context is lost if you do this ..
// // Thus not allowing for you to use variables .. const db in this case
// // If you still want this describe, you will have to use it like any other javascript function ... to expose the variables
// });
describe('Test Database function', () => {
// connect to database
before((done) => {
mongoose.connect('mongodb://127.0.0.1:27017/new_demo');
//Keep the url same which you use to debug you local application
db = mongoose.connection;
db.on('error', console.error.bind(console, 'Error connecting to DB'));
db.once('open', () => {
console.log('Connected to new_demo db');
done();
});
});
//Save something with value Mike Stevens, 19981
it('saves a new record', (done) => {
// Also if you want to increase the deafult timeout of a teast case
// you will have to change the => to function(), because of the way 'this' context behaves
// Thus :
// it('saves a new record', function(done) {
// this.timeout(10000);
// .. test case code
// }
var first_record = employee_details({
firstname: 'Mike',
lastname: 'Stevens',
id: 19981
});
first_record.save(function(err) {
if (err) return handleError(err);
// saved!
done();
//I used a simple callback function instead, makes life easier and code understable
})
});
after((done) => {
mongoose.connection.db.dropDatabase(() => {
mongoose.connection.close(done);
// I am guessing same goes here ..
// keep it simple !!
});
});
});
Now some theory, Ideally it is not recommend or rather not in the scope of a unit test case to actually connect to a database and/or modify the state of the external entity in any way (since you specifically mentioned that 'it is a unit test case').
A unit test should avoid making external calls or invoke actual API's. We should stub the call and in our test case assert that the call was made when we expected it to be, or when the appropriate input was provided.
Here's an example to walk the talk :
//This is myGLobalServiceLoactor which is used in actual code which is to be tested.
myGLobalServiceLoactor = {
database: {
save: sinon.stub(),
find: sinon.stub()
}
}
it('to check if external method is called ', () => {
let person_to_Save = {
//. . .
//. . .
}
proxyPersonInterface.savePerson(input_person).then((status) => {
// check if our stubbeb function is called
assert(myGLobalServiceLoactor.database.save.calledOnce);
});
});
And you can use helper libraries like Sinon and rewire to stub and proxy the actual modules in a unit test case. Hope that helps.
Upvotes: 1