node.js express route/controller 中基于承诺的单元测试代码
Unit testing promise based code in node.js express route/controller
最近,我在其余 api Express 应用程序中从使用回调切换到使用 Promise。
但是我在使用 promise 的异步行为进行单元测试 routes/controller 时遇到了麻烦。这是需要进行单元测试的示例代码。
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 存根到 return 已解决的承诺(Promise.resolve(用户))。但仍然异步执行回调。
我不确定我是否在测试 express 应用程序的正确轨道上。
在良好分离中测试这种代码的好策略是什么?
我也听说过使用超级测试。
但对我来说,使用 supertest 从 http 端点进行测试感觉更像是集成测试,它不是单元测试,而且非常昂贵。
此外,一般来说,我想知道尝试用单元测试(模型、控制器、中间件等)覆盖所有代码是否是一种好的做法,以及这样做的好的策略或技巧是什么。或者如果用 super test 来测试 http 端点就足够了。
如果您的测试方法没有 return 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
被调用而不是我们抛出信号它不是应该发生的事情。
最近,我在其余 api Express 应用程序中从使用回调切换到使用 Promise。 但是我在使用 promise 的异步行为进行单元测试 routes/controller 时遇到了麻烦。这是需要进行单元测试的示例代码。
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 存根到 return 已解决的承诺(Promise.resolve(用户))。但仍然异步执行回调。
我不确定我是否在测试 express 应用程序的正确轨道上。
在良好分离中测试这种代码的好策略是什么?
我也听说过使用超级测试。 但对我来说,使用 supertest 从 http 端点进行测试感觉更像是集成测试,它不是单元测试,而且非常昂贵。
此外,一般来说,我想知道尝试用单元测试(模型、控制器、中间件等)覆盖所有代码是否是一种好的做法,以及这样做的好的策略或技巧是什么。或者如果用 super test 来测试 http 端点就足够了。
如果您的测试方法没有 return 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
被调用而不是我们抛出信号它不是应该发生的事情。