我使用promises在(expressJS)路由的末尾包装异步(Mongo)DB操作。 我想尝试弄清楚如何测试以下代码。
userService
userService.findOne = function (id) {
var deferred = q.defer();
User.findOne({"_id" : id})
.exec(function (error, user) {
if (error) {
deferred.reject(error);
} else {
deferred.resolve(user);
}
});
return deferred.promise;
};
userRoute
var user = function (req, res) {
var userId = req.params.id
, userService = req.load("userService");
// custom middleware that enables me to inject mocks
return userService.findOne(id)
.then(function (user) {
console.log("called then");
res.json({
msg: "foo"
});
}).catch(function (error) {
console.log("called catch");
res.json({
error: error
});
}).done();
};
这是尝试使用mocha
测试上述内容userTest
it("when resolved", function (done) {
var jsonSpy = sinon.spy(httpMock.res, "json")
, httpMock = require("/path/to/mock/http/object")
, serviceMock = require("/path/to/mock/service"),
, deferred = q.defer()
, findStub = sinon.stub(serviceMock, "findOne")
.returns(deferred.promise)
, loadStub = sinon.stub(httpMock.req, "load")
.returns(serviceMock),
retPromise;
// trigger route
routes.user(httpMock.req, httpMock.res);
// force promise to resolve?
deferred.resolve();
expect(jsonSpy.called).to.be.true; // fails
// chai as promised
retPromise = findStub.returnValues[0];
expect(retPromise).to.be.fulfilled; // passes
});
http mock只是一个没有操作的空对象,expressJS通常会开始渲染东西。我在这些无操作中添加了一些日志记录,以便了解它是如何挂在一起的。
这并不是很有效。我想验证整体是如何整合的,以建立某种回归套件 - 但我已经有效地嘲笑了它,并且我只是测试我的模拟(不完全成功)。
我还注意到控制台登录我的http模拟内部由then和catch触发了两次 - 但是在实际代码中调用的jsonSpy(通过在userRoute代码中注销sinon间谍来验证)没有在测试中调用。
有没有人对Mongo支持的快递应用程序的集成测试策略有所建议?
答案 0 :(得分:0)
在你检查结果是否被调用之前,我认为你并没有给你的承诺一个机会。在设置jsonSpy.called之前,您需要异步等待userService.findOne()的promise链完成。试试这个:
// start of code as normal
q.when(
routes.user(httpMock.req, httpMock.res),
function() { expect(jsonSpy.called).to.be.true; }
);
deferred.resolve();
// rest of code as normal
那应该链接routes.user()promise并按预期传递。
提醒一句:我不熟悉您的框架,所以我不知道它是否会耐心地等待所有异步事件发生。如果它给你回调你的延迟链时遇到问题,你可能想尝试使用nodeunit,它可以很好地处理异步测试(IMO)。