ritmatter ritmatter - 3 months ago 34
Javascript Question

Jasmine spyOn mongoose save

I'd like to mock the save() function of a Mongoose model. The function I want to test looks like this in a file called user.js:

var User = import('User.js')

post: function(req, res) {
var user = new User({
password : req.body.password,
email : req.body.email,
});
user.save( function(err) {
if (err) {
....
} else {
....
}
});


I tried to write a test that looks like this in another file called user_spec.js:

var Hander = require('user.js')

it('works properly', function() {
spyOn(User, 'save').andReturn(null)
Handler.post(req, res);
});


but that gives me the error:

save() method does not exist


I've done some more digging and it looks like the User model itself does not have the save() method, an instance does. This would mean I have to mock the constructor of User, but I'm having a lot of trouble with this. Other posts refer to a statement like:

spyOn(window, User)


to fix this, but in NodeJS, global (the window equivalent here), does not have User, since I import is as a variable. Is it possible to mock the constructor to give me something with a mocked save()? I've also taken a look at an npm module called rewire, but I was hoping I could do this without mocking and replacing the entire user module in my handler.

Answer

This does not solve the issue of mocking a local variable, but it will solve the issue of unit testing the creation of new documents.

When creating a new document, it is better to use Model.create(). This can be mocked effectively, and it is simply less code. The right way to handle this and test it would be:

var User = import('User.js')

post: function(req, res) {
  User.create({
      password    : req.body.password,
      email       : req.body.email,
  }, function(err) {
    if (err) {
      ....
    } else {
      ....
    }
  });
});

Corresponding test:

var Hander = require('user.js')

it('works properly', function() {
  spyOn(User, 'create').andReturn(null)
  Handler.post(req, res);
});

Hopefully this workaround will help other people getting frustrated with jasmine and mongoose unit testing.