I'm relatively new to Node and Sinon. This application was made with Express, and I'm using Mocha, Chai, and Sinon. Using Sinon-Chai, I'm POST testing routes in Express with multiple callbacks, and can't figure out how to check second and subsequent callbacks.
The route inside my index.js is:
var controller = require('./example.controller');
var validator = require('./example.validator');
var router = express.Router();
router.post('/', validator.create, controller.create);
In my validator.js is the validator.create which checks the submitted parameter:
exports.create = function(req, res, next) {
var valid = true;
var errorMessages = [];
if (req.body.name) {
patt = /[^a-zA-Z0-9 !@#$%^&*()_+\-=\[\]{};':]/g;
if (patt.test(req.body.name)) {
valid = false;
errorMessages.push("Parameter is not alphanumeric");
}
}
if (valid == false) {
return res.status(400).json(errorMessages);
}
next();
}
In my controller.js is the controller.create which creates a entry in the DB:
exports.create = function(req, res) {
return Example.create(req.body)
.then(baseController.respondWithResult(res, 201))
.catch(baseController.handleError(res));
}
The Sinon-Chai tests in my index.spec.js:
var proxyquire = require('proxyquire').noPreserveCache();
var exampleCtrlStub = {
create: 'exampleCtrl.create',
};
var exampleValidatorStub = {
create: 'exampleValidator.create'
}
var routerStub = {
get: sinon.spy(),
put: sinon.spy(),
patch: sinon.spy(),
post: sinon.spy(),
delete: sinon.spy()
};
var exampleIndex = proxyquire('./index.js', {
express: {
Router() {
return routerStub;
}
},
'./example.controller': exampleCtrlStub,
'./example.validator': exampleValidatorStub
});
describe('POST /api/examples', function() {
it('should route to example.validator.create', function() {
routerStub.post
.withArgs('/', 'exampleValidator.create')
.should.have.been.calledOnce;
});
});
describe('POST /api/examples', function() {
it('should route to example.controller.create', function() {
routerStub.post
.withArgs('/', 'exampleCtrl.create')
.should.have.been.called;
});
});
Though expecting both tests to pass, the first test (validator.create) passes but the second one (controller.create) fails. I've not been able to find a way to test that the controller.create is called.
in the second test, we can't skip the first validator argument using withArgs
. The test is failed because it is looking for a method with this signature which is not exist in source.
router.post('/', controller.create);
withArgs
always start with the first then second argument, etc. So, the solution is to include the validator in the test
routerStub.post
.withArgs('/', 'exampleValidator.create', 'exampleCtrl.create')
.should.have.been.called;
Reference:
Hope it helps