最近我在我的rest api express app中使用回调切换到使用promise。 但我遇到了单元测试路由/控制器与承诺异步行为的问题。以下是需要进行单元测试的示例代码。
var handler = function (req, res, next) {
var query = {},
var options = {
sort: { updatedAt: -1 },
limit: 10
};
if (req.query.before) {
query.updatedAt = { $lt: req.query.before };
}
// User.findAsync returns bluebird promise
User.findAsync(query, null, options).then(function (user) {
res.json(user);
}).catch(function (e) {
next(e);
});
}
router.get('/api/users', handler);
我测试上面代码的方法是监视req,next和User.findAsync并检查它们是否使用正确的参数调用。但由于承诺的异步行为,我无法检查res.json或next是否被调用。
我尝试将findAsync存根以返回已解析的promise(Promise.resolve(user))。但仍然会以异步方式执行回调。
我不确定我是否正在测试快递应用程序。
在良好的分离中测试这种代码的好策略是什么?
我也听说过使用supertest。 但对我来说,使用supertest从http端点进行测试感觉就像更多的集成测试,这不是单元测试而且非常昂贵。
此外,一般来说,我想知道尝试用单元测试(模型,控制器,中间件等)覆盖所有代码以及这样做的好策略或技术是否是好的做法。或者如果它足以用超级测试来测试http端点。
答案 0 :(得分:4)
如果您测试的方法未返回promise,则您无法在Mocha中使用promise语法。您可以像测试任何其他异步方法一样测试方法 - done
作为it
的参数。假设我们要测试您的handler
函数:
var handler = function (req, res, next) {
//...
User.findAsync(query, null, options).then(function (user) {
res.json(user);
}).catch(function (e) {
next(e);
});
}
我们可以这样写一个测试:
describe("The handler", function(){
it("calls res.json", function(done){ // note the done argument
handler({query: {before: 5}, // mock request
{json: done} // res.json calls our `done` param of this function
function(){ throw new Error("error called"); });
});
});
请注意,我们模拟了请求,响应和next
处理程序。我们的模拟响应有一个json方法,让测试知道它是完整的(如果你想在其中进行断言,这可以是一个函数),如果调用next
而不是我们抛出信号它不是假设的东西即将发生。