如何在 Mongo(ose)/Express 应用程序中测试 Promise?
Posted
技术标签:
【中文标题】如何在 Mongo(ose)/Express 应用程序中测试 Promise?【英文标题】:How to test promises in Mongo(ose)/Express app? 【发布时间】:2014-05-14 09:07:03 【问题描述】:我正在使用 Promise 在 (expressJS) 路由的末尾包装异步 (Mongo) 数据库操作。 我想尝试弄清楚如何测试以下代码。
用户服务
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;
;
用户路由
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 测试上述内容
用户测试
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 spy 来验证)不是在测试中调用。
有没有人对 Mongo 支持的快速应用程序的集成测试策略提出一些建议?
【问题讨论】:
从最近开始,您可以从 mocha 测试中return
承诺并让测试成功拒绝,而不必在履行处理程序中显式调用 done()
并在拒绝处理程序中显式失败。顺便检查一下 chai 的承诺断言
如果您查看我的示例,您会发现我已经在使用 Chai-as-promised
为了 100% 公平,我看到你是 - 我只是想把它偷偷放在这里,因为人们将来可能会遇到这个问题,我希望明确指出。顺便说一句,好问题,会分享我自己的经验,但我希望 Domenic 能出现并分享他的见解。
【参考方案1】:
在我看来,在您检查结果是否已被调用之前,您并没有给您的承诺一个触发的机会。在设置 jsonSpy.call 之前,您需要异步等待 userService.findOne() 的承诺链完成。试试这个:
// 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() 承诺并按预期通过。
提醒一句:我不熟悉你的框架,所以我不知道它是否会耐心等待所有异步事件发生。如果它给你回拨到你的延迟链带来问题,你可能想尝试nodeunit,它可以很好地处理异步测试(IMO)。
【讨论】:
以上是关于如何在 Mongo(ose)/Express 应用程序中测试 Promise?的主要内容,如果未能解决你的问题,请参考以下文章
应用安全 - 数据库 | 工具 - mongo数据库 - mongo-express - 漏洞 - 汇总
你能告诉我 express-mongo-sanitize 是不是有效吗?
NodeJS + Express + Mongo Session 存储
如何从服务器端 express/mongo/mongoose 中的 URL,客户端的 axios/react/redux 中获取参数 ID