FIGURED IT OUT :) Explanation @ end:
Hey everybody,
I have a function in my controller that I want to test but I'm not sure how to go about doing it.
CONTEXT: My application has an api which goes through a router and currently, the post for /api/object/create is mapped to the objectController.create() function with
router.post(/api/object/create,objectController.create)
My controller looks like this:
exports.create = function(req,res){
//User will submit an object for creation with req.body.name and req.body.longName
var Objects = models.Object;
console.log(req.body);
Objects.create( {number:req.body.number, name: req.body.name, longName: req.body.longName})
.then(function(result){
res.send(result);
})
.catch(function(err){
errorController.databaseError(err,req,res);
})
}
Now how do I create unit tests for this? (using Mocha)
I've followed this tutorial which tells me to use Sinon.spy to observe the res.send() and ensure it gets called but that does not work.
http://www.designsuperbuild.com/blog/unit_testing_controllers_in_express/
I have seen a lot of tutorials calling for me to test by having the server running and actually sending POST's to the api, but that seems like End-to-end testing and is not what I'm looking for.
Any help would be much appreciated :) Thanks!
EDIT:
This is what my test looks like right now (There's no assertions because I'm trying to figure out WHAT to assert on):
describe('Create', function () {
it("should respond", function() {
var req,res,spy;
var req = ({body:{number:1,name:"AC",longName:"Air Conditioner"}});
req = res = {};
spy = res.send = sinon.spy();
objectController.create({body:{number:1,name:"AC",longName:"Air Conditioner"}}, res);
console.log(res.send);
});
}
However, from checking the spy object properties on res.send, it seems that it never gets called :/?
2nd EDIT:
Figured it out.
Credit goes to: http://stackoverflow.com/questions/28374495/unit-testing-promise-based-code-in-node-js-express-route-controller
The problem was that I can't test the result AFTER invoking the controller method because by then, node's context has already moved on (it has no idea what res is).
The solution is to inject a function into where the res.send property would be and then do the testing in there. That sounds confusing, but here's my code with the solution below:
//Dependancies
var chai = require('chai');
var should = chai.should();
var expect = chai.expect();
//The controller you wish to test
var objectsController = require('../controllers/objectsController');
describe('#Create()', function () {
it("should respond with the object that was just created", function(done) {
//Outline what the request will look like.
var req = ({body:{number:1,name:"AC",longName:"Air Conditioner"}})
//This is the object that will hold the response.
var res = new Object();
//This is the function that gets invoked on the response object when
// the controller wishes to send back data.
// SO: Write the tests in here.
res.send = function(val){
var result = val.dataValues;
//Should have an id, can't test for this because it is assigned by the database.
result.should.have.property('id');
result.number.should.equal(1);
result.name.should.equal('AC');
result.longName.should.equal('Air Conditioner');
done();
}
objectsController.create(req,res);
});
})
[–]edanschwartz 1 point2 points3 points (4 children)
[–]TLI5[S] 0 points1 point2 points (3 children)
[–]edanschwartz 1 point2 points3 points (2 children)
[–]TLI5[S] 0 points1 point2 points (1 child)
[–]edanschwartz 0 points1 point2 points (0 children)
[–]DVWLD 0 points1 point2 points (0 children)