Unit Testing Controllers the Easy Way in Express 4
Express 4 is a great upgrade to Express (find out more about the changes in this great article) and allows us to easily modularize our routes. If we go a little bit further we can also easily test our routes without mocking out the whole of Express.
Generating the Express 4 app skeleton using the Express CLI we get this:
// file:/app.js
// require route files
var users = require('./routes/users');
//... later in app.js use the routes
app.use('/users', users);
// file:/routes/users.js
var express = require ('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res) {
res.send('respond with a resource');
});
module.exports = router;
This is pretty hard to unit test - we'd need to stub out the Express require call using something like proxyquire.
If we make a couple of changes we can make this much simpler. First lets move the actual router to it's own file.
// file:/routes/users/getUsers.js
function getUsers(req, res) {
res.send('respond with a resource');
}
module.exports = getUsers;
Simple, no Express dependencies - now lets wire this into Express in our main users routes file.
// file:/routes/users.js
var express = require('express');
var router = express.Router();
var getUsers = require('./users/getUsers');
router.get('/', getUsers);
module.exports = router;
All good, now we can easily unit test this route and we'll only need to mock out it's real dependencies. Using Mocha a simple test would look something like this:
var sinon = require('sinon');
var chai = require('chai');
var expect = chai.expect;
var getUsers = require('../../app/routes/users/getUsers');
describe("Routes", function() {
describe("GET Users", function() {
it("should respond", function() {
var req,res,spy;
req = res = {};
spy = res.send = sinon.spy();
getUsers(req, res);
expect(spy.calledOnce).to.equal(true);
});
});
});