chovy
chovy

Reputation: 75656

how do i use should with mocha and mongoose?

I keep getting an error in the save() method when I run the test.

var User = require('../../models/user')
, should = require('should');

describe('User', function(){
  describe('#save()', function(){
    it('should save without error', function(done){
      var user = new User({
        username    : 'User1'
        , email     : '[email protected]'
        , password  : 'foo'
      });
      user.save(function(err, user){
        if (err) throw err;

        it('should have a username', function(done){
          user.should.have.property('username', 'User1');
          done();
        });
      });
    })
  })

})

here is the error:

$ mocha test/unit/user.js

  ․

  ✖ 1 of 1 test failed:

  1) User #save() should save without error:
     Error: timeout of 2000ms exceeded
      at Object.<anonymous> (/usr/local/lib/node_modules/mocha/lib/runnable.js:1
61:14)
      at Timer.list.ontimeout (timers.js:101:19)

Upvotes: 8

Views: 3853

Answers (1)

rorymadden
rorymadden

Reputation: 954

You can nest describes but not it tests. Each test is meant to be stand alone so when you are looking through your results you can see where it is failing - on the save or not having the username property. For example in your code above there is no way for it to fail the 'should save without error' test as there is no done(). Which is also the reason the code above is timing out: mocha cannot find the done() for the 'should save without error' test.

Being able to nest describes is very powerful though. Within each describe you can have a before, beforeEach, after and afterEach statement. With these you can achieve the nesting that you are attempting above. See the mocha docs for more information if you want to read up on these statements.

The way I would write what you are trying to achieve is as follows:

var User = require('../../models/user')
    , should = require('should')
    // this allows you to access fakeUser from each test
    , fakeUser;

describe('User', function(){
  beforeEach(function(done){
    fakeUser = {
      username    : 'User1'
      , email     : '[email protected]'
      , password  : 'foo'
    }
    // this cleans out your database before each test
    User.remove(done);
  });

  describe('#save()', function(){
    var user;
    // you can use beforeEach in each nested describe
    beforeEach(function(done){
      user = new User(fakeUser);
      done();
    }

    // you are testing for errors when checking for properties
    // no need for explicit save test
    it('should have username property', function(done){
      user.save(function(err, user){
        // dont do this: if (err) throw err; - use a test
        should.not.exist(err);
        user.should.have.property('username', 'User1');
        done();
      });
    });

    // now try a negative test
    it('should not save if username is not present', function(done){
      user.username = '';
      user.save(function(err, user){
        should.exist(err);
        should.not.exist(user.username);
        done();
      });
    });
  });
});

Upvotes: 7

Related Questions