I'm new to unit testing in NodeJS using Mocha, Chai and Sinon. I have been trying to write a unit test case for an API end-point and am struggling with testing if res.status(200).send();
is called from the API inside a Promise resolution. Below is the code:
controller.js - Has the function to be unit tested
const User = require("./user_model");
module.exports = {
getUserById(req, res) {
const { params: reqParams } = req,
{ userId } = reqParams;
User.findOne({ _id: userId })
.exec()
.then(function(userFromDb) {
res.status(200).send(); // unable to test if this is getting called.
})
.catch((err) => res.status(500).send());
}
};
test.js - Has the unit test
const sinon = require("sinon"),
User = require("./user_model"),
controller = require("../controller");
require("sinon-mongoose");
describe('users', function() {
it('getUserById', function() {
const validReqObj = {
params: {
userId: "123"
}
};
const mock = sinon.mock(User);
mock.expects("findOne").withArgs({ _id: validReqObj.params.userId })
.chain("exec")
.resolves({ _id: validReqObj.params.userId });
const validRes = {
status: function(statusCode) {
sinon.assert.match(statusCode, 200);
return {
send: function() {
}
};
}
};
controller.getUserById(validReqObj, validRes);
mock.restore();
mock.verify();
});
});
As you can see, my test does 2 things:
findOne
function and tests if the promise resolution of findOne
is fine or not. res.status()
gets called with a 200 status code. It doesn't test if res.status()
even gets called. For example, if I remove the line res.status(200).send();
from controller.js , the test still passes.
I tried creating spy on res.status
. It doesn't work as expected.
The issue is your code has nothing to indicate when the asynchronous function has finished. While we could add a timer into the test to solve this, it's a bit crap solution.
The easiest way to solve this in a nice way is to return the promise from your function:
return User.findOne({ _id: userId })
....
After this, in your test you can simply do something like this:
return controller.getUserById(validReqObj, validRes).then(function() {
mock.restore();
mock.verify();
});
Note the return in the test as well - this allows mocha to detect it's an async test with a promise.
It's because getUserById
is asynchronous function. Even when you've created mock for User
model, getUserById
is still asynchronous.
To create proper test, you can do the following:
getUserById
function and create a promise chain it test. supertest
module which to send a real http request and validate response.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.