So I'm working on an express.js app where I have a mongoose model User. I wrote a test file (using Mocha) to test the save() function but all of my tests are taking too long to execute and ultimately timeout.
Here are the errors I'm getting:
Testing - Server - User - Model
Testing save()
1) should be able to save without problems
2) should fail to save an exisitng user again
3) should should an error when try to save with empty email
4) should give an error when try to save with empty password
5) "after all" hook
0 passing (8s)
5 failing
1) Testing - Server - User - Model Testing save() should be able to save without problems:
Error: timeout of 2000ms exceeded
at null.<anonymous> (/usr/local/lib/node_modules/mocha/lib/runnable.js:159:19)
at Timer.listOnTimeout [as ontimeout] (timers.js:112:15)
2) Testing - Server - User - Model Testing save() should fail to save an exisitng user again:
Error: timeout of 2000ms exceeded
at null.<anonymous> (/usr/local/lib/node_modules/mocha/lib/runnable.js:159:19)
at Timer.listOnTimeout [as ontimeout] (timers.js:112:15)
3) Testing - Server - User - Model Testing save() should should an error when try to save with empty email:
Error: timeout of 2000ms exceeded
at null.<anonymous> (/usr/local/lib/node_modules/mocha/lib/runnable.js:159:19)
at Timer.listOnTimeout [as ontimeout] (timers.js:112:15)
4) Testing - Server - User - Model Testing save() should give an error when try to save with empty password:
Uncaught AssertionError: expected null to exist
at Promise.<anonymous> (/Users/Mukul/PersonalProjects/ResourceBucket/test/models/user.server.model.test.js:69:12)
at Promise.<anonymous> (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/node_modules/mpromise/lib/promise.js:177:8)
at Promise.emit (events.js:98:17)
at Promise.emit (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/node_modules/mpromise/lib/promise.js:84:38)
at Promise.fulfill (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/node_modules/mpromise/lib/promise.js:97:20)
at handleSave (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/lib/model.js:133:13)
at /Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/lib/utils.js:408:16
at model.save (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/lib/model.js:222:7)
at model._done (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/node_modules/hooks/hooks.js:59:24)
at _next (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/node_modules/hooks/hooks.js:52:28)
at fnWrapper (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/node_modules/hooks/hooks.js:159:8)
at model.<anonymous> (/Users/Mukul/PersonalProjects/ResourceBucket/models/user.js:22:46)
at _next (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/node_modules/hooks/hooks.js:50:30)
at fnWrapper (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/node_modules/hooks/hooks.js:159:8)
at complete (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/lib/document.js:992:5)
at /Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/lib/document.js:983:20
at ObjectId.SchemaType.doValidate (/Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/lib/schematype.js:603:22)
at /Users/Mukul/PersonalProjects/ResourceBucket/node_modules/mongoose/lib/document.js:974:9
at process._tickCallback (node.js:442:13)
5) Testing - Server - User - Model "after all" hook:
Error: timeout of 2000ms exceeded
at null.<anonymous> (/usr/local/lib/node_modules/mocha/lib/runnable.js:159:19)
at Timer.listOnTimeout [as ontimeout] (timers.js:112:15)
Here's my test file:
// Module dependencies
var should = require("should");
var mongoose = require("mongoose");
var config = require('../../config/config');
var nodemailer = require('nodemailer');
var bcrypt = require('bcryptjs');
// Get User model
var User = require('../../models/user')(mongoose, config, bcrypt, nodemailer).User;
// Define global test variables
var user;
var user2;
// Unit tests
describe('Testing - Server - User - Model', function(){
// Since its before - it happens once ONCE before ALL the tests
before(function(done){
// Since we're using the global variables don't use var in front of them
user = new User({
email: 'a@a.com',
password: 'a'
});
// Another user with same details as the first user cos
// For a test case, where we try to insert 2 records with same details (should fail as exprected)
user2 = new User({
email: 'a@a.com',
password: 'a'
});
done();
});
// Testing function #1 - save()
describe('Testing save()', function(){
// Test case #1 - save normally
it('should be able to save without problems', function(done){
try {
user.save(done);
} catch (x) {
done(x);
}
});
// Test case #2 - should fail to save an exisitng user again
it('should fail to save an exisitng user again', function(done){
user.save(function(){
user2.save(function(err){
should.exist(err);
done();
});
});
})
// Test case #3 - should give an error when try to save with empty email
it('should should an error when try to save with empty email', function(done){
user.email = '';
return user.save(function(err){
should.exist(err);
done();
});
});
// Test case #4 - should give an error when try to save with empty password
it('should give an error when try to save with empty password', function(done){
return user.save(function(err){
should.exist(err);
done();
});
});
});
after(function(done){
User.remove().exec(done);
});
});
and here's my User model file:
module.exports = function(mongoose, config, bcrypt, nodemailer){
// User schema
var userSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
lowercase: true
},
password: {
type: String,
select: false
}
});
// Makes sure that our passwords are always hashed before saving to the database
// Refer to sessionBuddy's resources for more info on this
userSchema.pre('save', function(next) {
var user = this;
// Only hash the password if its modified or new
if (!user.isModified('password')) return next();
// Generate salt
bcrypt.genSalt(config.SALT_WORK_FACTOR, function(err, salt) {
if (err) return next(err);
// hash the password along with the salt
bcrypt.hash(user.password, salt, function(err, hash) {
if (err) return next(err);
// overwrite the cleartext password with the hashed one
user.password = hash;
next();
});
});
});
// Password verification for cleartext and hashed passwords
userSchema.methods.comparePassword = function(password, done) {
bcrypt.compare(password, this.password, function(err, isMatch) {
done(err, isMatch);
});
};
var User = mongoose.model('User', userSchema);
return{
User : User
}
}
I also tried the try/catch way for promises from this thread: In mocha testing while calling asynchronous function how to avoid the timeout Error: timeout of 2000ms exceeded. But that didn't work either.
Any help is appreciated! Thanks
EDIT: As suggested in the comments I wasn't connecting to the database in the test file. EDIT2: Getting the following error with the last 2 tests now - "Uncaught AssertionError: expected null to exist" EDIT3: Actually my schema was okay with saving "email" and "password" empty since I wasn't setting the required field true, after updating my schema, it works.