I am failing at trying to validate that my controller (get method) is doing what it should under different inputs. In this case, I am trying to spy the res.json method in order to check it is called once when I pass the required inputs to the controller.
This is my broadcast controller (I am testing the get method):
'use strict';
module.exports = function(models) {
var controller = {
get: get
};
function get(req, res, next) {
models.Broadcast.findById(req.params.id)
.then(function(broadcast) {
console.log(res);
res.json(broadcast);
})
.catch(function(err) {
next(err);
});
}
return controller;
};
As you can see, It receive a models object which contain a Broadcast object that expose the findById method (this method query the DB to get a broadcast instance with the id equal to req.params.id).
So, using tape and simon packages, I created the next test:
'use strict';
var test = require('tape');
var sinon = require('sinon');
test('Broadcast controller.get', function(assert) {
// Create a fake broadcast object
var broadcast = {
id: 1,
message: 'dummy',
popularity: 0
};
// Mock the models object
var models = {};
models.Broadcast = {};
// Create a stub of the findById object (it should return a promise)
models.Broadcast.findById = sinon.stub().returns(Promise.resolve(broadcast));
// Require the broadcast controller passing the models object
var broadcastCtlr = rootRequire('controllers/api/broadcasts/broadcasts')(models);
// Mock the req, res and next parameters (used by the get method=
var req, res, next;
req = {
params: {
id: 1
}
};
res = {};
// Create a stub for the json method (this one must be called once)
res.json = sinon.stub().returns(broadcast);
// Create a spy on the next (I will use this to test the error case)
next = sinon.spy();
// A basic assertion
assert.ok(broadcastCtlr.get, 'the controller was successfully loaded');
// Execute the controller
broadcastCtlr.get(req, res, next);
// Assert that the findById method was correctly called
assert.ok(models.Broadcast.findById.calledOnce, 'findById called once');
assert.ok(models.Broadcast.findById.calledWith(1), 'findById called with id = 1');
// Assert that the res.json method was correctly called (this is not working)
assert.ok(res.json.calledOnce, 'the json response was sent');
assert.ok(res.json.calledWith(broadcast), 'controller must return res.json(broadcast)');
// Assert that the next method was not called (this is ok)
assert.notOk(next.calledOnce, 'next should not be called (no error)');
assert.end();
});
After running this test, the assertions about the res.json method failed and I can't understand why they are failing.
This is the output:
# Broadcast controller.get
ok 1 the controller was successfully loaded
ok 2 findById called once
ok 3 findById called with id = 1
not ok 4 the json response was sent
---
operator: ok
expected: true
actual: false
at: Test.<anonymous> (/Users/rcanepa/Development/colossus/lifePartner/express-version/test/unit/controllers/broadcasts.js:51:10)
...
not ok 5 controller must return res.json(broadcast)
---
operator: ok
expected: true
actual: false
at: Test.<anonymous> (/Users/rcanepa/Development/colossus/lifePartner/express-version/test/unit/controllers/broadcasts.js:52:10)
...
ok 6 next should not be called (no error)
1..6
# tests 6
# pass 4
# fail 2
Finally, something weird I noticed is that if I test the execution of the res.json method (console.log(res.json.calledOnce)) inside the controller, it returns true. Why would it return true in my controller but not in the test's scope?
I probed this adding this line to my get method:
...
.then(function (broadcast)
res.json(broadcast);
console.log(res.json.calledOnce); // return true!!!
})
...
Aucun commentaire:
Enregistrer un commentaire