Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 743
ritmatter Avatar asked Dec 29 '14 05:12

ritmatter


1 Answers

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.

like image 58
ritmatter Avatar answered Nov 03 '22 20:11

ritmatter