我是使用Mocha,Chai和Sinon在NodeJS中进行单元测试的新手 . 我一直在尝试为API endpoints 编写一个单元测试用例,如果在Promise解决方案中从API调用 res.status(200).send();
,我正在努力测试 . 以下是代码:
controller.js - 具有单元测试功能
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 - 是否有单元测试
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();
});
});
如您所见,我的测试做了两件事:
-
模拟mongoose
findOne
函数并测试findOne
的承诺分辨率是否正常 . -
断言使用200状态代码调用
res.status()
.
它不测试 res.status()
是否被调用 . 例如,如果我从controller.js中删除行 res.status(200).send();
,则测试仍然通过 .
我尝试在 res.status
上创建spy . 它没有按预期工作 .
2 回答
问题是你的代码没有任何东西可以指示异步函数何时完成 . 虽然我们可以在测试中添加一个计时器来解决这个问题,但它有点废话解决方案 .
以一种很好的方式解决这个问题的最简单方法是从函数中返回promise:
在此之后,在您的测试中,您可以简单地执行以下操作:
注意测试中的返回 - 这允许mocha检测它是带有promise的异步测试 .
这是因为
getUserById
是异步函数 . 即使您为User
模型创建了模拟,getUserById
仍然是异步的 .要创建正确的测试,您可以执行以下操作:
从
getUserById
函数返回promise并创建一个它测试的promise链 .使用
supertest
模块发送真实的http请求并验证响应 .