Static Version

Mocking Dependencies using [rewire]

Despite all my efforts to try to encapsulate some of my code into my modules, I was always founding myself exposing too much just for unit testing purpose. And even thought, it was often very complex to mock out some of the external libraries I was using. That was before I found the rewire library. As they say, it only: "adds a special setter and getter to modules so you can modify their behaviour for better unit testing".

This is all you need!

Let's see an example

I have a very simple controller like this:

user-controller.js
'use strict';

var userService = require('../service/user-service');

exports
.allUsers = function (req, res, next) {

  userService
.getUsers(function (err, users) {
   
if (err) {
     
return next(err);
   
}
    res
.json(users);
 
});
};

In my test driven development all I want to test is:

  • this method will call getUsers on userService
  • if the callback receive an error then it will call next passing the error
  • else json is called on the response with the users as arguments

Setting up a mock is easy (I use sinon but any mocking will do it):

// given
var userController = require('./user-controller'),
    userServiceMock
= {};

// and
userServiceMock
.getUser = sinon.stub().callsArgWith(1, null, [{id: 'user1'}, {id: 'user2'}]);

// when
userController
.allUsers();

// then
userServiceMock
.getUser.calledOnce.should.equal(true);

But how can I inject the mock instead of the real user service ?

=> Rewire!

Instead of require the user-controller I'm using rewire:

var userController = rewire('./user-controller')

Then I can get and set any properties on the module. So I can do:

before(function(){
    userController
.__set__({
       
'userService': userServiceMock
   
});
});

Et voila!

Here is the full test for the previous controller:

user-controller.spec.js
'use strict';

var sinon = require('sinon'),
    rewire
= require('rewire'),
    userController
= rewire('./user-controller');

describe
('allUsers', function() {

  it
('should return all users',function() {

   
// given
   
var userServiceMock = {},
        res            
= { json: sinon.spy()},
        users          
= [{id: 'user1'}, {id: 'user2'}],
        nextStub        
= sinon.stub();

   
// and
    userServiceMock
.getUser = sinon.stub().callsArgWith(1, null, users);

   
// when
    userController
.allUsers({}, res, nextStub);

   
// then
    res
.json.calledWith(users).should.equal(true);
    nextStub
.called.should.equal(false);
 
});
});

View the discussion thread.blog comments powered byDisqus