title: Mocha tests taking too long to execute
body: <p>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. </p>
  
  <p>Here are the errors I'm getting: </p>
  
  <pre><code>  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.&lt;anonymous&gt; (/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.&lt;anonymous&gt; (/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.&lt;anonymous&gt; (/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.&lt;anonymous&gt; (/Users/Mukul/PersonalProjects/ResourceBucket/test/models/user.server.model.test.js:69:12)
        at Promise.&lt;anonymous&gt; (/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.&lt;anonymous&gt; (/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.&lt;anonymous&gt; (/usr/local/lib/node_modules/mocha/lib/runnable.js:159:19)
        at Timer.listOnTimeout [as ontimeout] (timers.js:112:15)
  </code></pre>
  
  <p>Here's my test file:</p>
  
  <pre><code>// 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);
      });
  });
  </code></pre>
  
  <p>and here's my User model file: </p>
  
  <pre><code>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
    }
  }
  </code></pre>
  
  <p>I also tried the try/catch way for promises from this thread: <a href="https://stackoverflow.com/questions/16607039/in-mocha-testing-while-calling-asynchronous-function-how-to-avoid-the-timeout-er">In mocha testing while calling asynchronous function how to avoid the timeout Error: timeout of 2000ms exceeded.</a> But that didn't work either. </p>
  
  <p>Any help is appreciated! 
  Thanks</p>
  
  <p>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. </p>