使用 Mocha 测试 Express 和 Mongoose
Testing Express and Mongoose with Mocha
我正在尝试使用 Mocha 和 Chai 测试我的 REST API 端点处理程序,该应用程序是使用 Express 和 Mongoose 构建的。我的处理程序主要采用以下形式:
var handler = function (req, res, next) {
// Process the request, prepare the variables
// Call a Mongoose function
Model.operation({'search': 'items'}, function(err, results) {
// Process the results, send call next(err) if necessary
// Return the object or objects
return res.send(results)
}
}
例如:
auth.getUser = function (req, res, next) {
// Find the requested user
User.findById(req.params.id, function (err, user) {
// If there is an error, cascade down
if (err) {
return next(err);
}
// If the user was not found, return 404
else if (!user) {
return res.status(404).send('The user could not be found');
}
// If the user was found
else {
// Remove the password
user = user.toObject();
delete user.password;
// If the user is not the authenticated user, remove the email
if (!(req.isAuthenticated() && (req.user.username === user.username))) {
delete user.email;
}
// Return the user
return res.send(user);
}
});
};
问题在于函数 returns 在调用 Mongoose 方法和测试用例时是这样的:
it('Should create a user', function () {
auth.createUser(request, response);
var data = JSON.parse(response._getData());
data.username.should.equal('some_user');
});
永远不会通过,因为函数在执行任何操作之前 returning。使用 Mockgoose 模拟 Mongoose,使用 Express-Mocks-HTTP 模拟请求和响应对象。
虽然使用 superagent 和其他请求库相当普遍,但我更愿意单独测试功能,而不是测试整个框架。
有没有办法让测试在评估 should 语句之前等待,而无需将我正在测试的代码更改为 return promises?
您应该使用异步版本的测试,方法是向 it
提供一个带有 done
参数的函数。
有关详细信息,请参阅 http://mochajs.org/#asynchronous-code。
由于您不想修改代码,一种方法是在测试中使用 setTimeout
等待调用完成。
我会尝试这样的事情:
it('Should create a user', function (done) {
auth.createUser(request, response);
setTimeout(function(){
var data = JSON.parse(response._getData());
data.username.should.equal('some_user');
done();
}, 1000); // waiting one second to perform the test
});
(可能有更好的方法)
显然,express-mocks-http 前段时间被废弃了,新的代码在 node-mocks-http 下。使用这个新库,可以使用事件执行我要求的操作。它没有记录,但查看代码你可以弄明白。
创建响应对象时必须传递 EventEmitter 对象:
var EventEmitter = require('events').EventEmitter;
var response = NodeMocks.createResponse({eventEmitter: EventEmitter});
然后,在测试中,您向事件 'end' 或 'send' 添加一个侦听器,因为它们都在调用 res.send 时被触发。 'end' 涵盖的内容超过 'send',以防您有 res.send 以外的呼叫(例如,res.status(404).end().
测试看起来像这样:
it('Should return the user after creation', function (done) {
auth.createUser(request, response);
response.on('send', function () {
var data = response._getData();
data.username.should.equal('someone');
data.email.should.equal('asdf2@asdf.com');
done();
});
});
我正在尝试使用 Mocha 和 Chai 测试我的 REST API 端点处理程序,该应用程序是使用 Express 和 Mongoose 构建的。我的处理程序主要采用以下形式:
var handler = function (req, res, next) {
// Process the request, prepare the variables
// Call a Mongoose function
Model.operation({'search': 'items'}, function(err, results) {
// Process the results, send call next(err) if necessary
// Return the object or objects
return res.send(results)
}
}
例如:
auth.getUser = function (req, res, next) {
// Find the requested user
User.findById(req.params.id, function (err, user) {
// If there is an error, cascade down
if (err) {
return next(err);
}
// If the user was not found, return 404
else if (!user) {
return res.status(404).send('The user could not be found');
}
// If the user was found
else {
// Remove the password
user = user.toObject();
delete user.password;
// If the user is not the authenticated user, remove the email
if (!(req.isAuthenticated() && (req.user.username === user.username))) {
delete user.email;
}
// Return the user
return res.send(user);
}
});
};
问题在于函数 returns 在调用 Mongoose 方法和测试用例时是这样的:
it('Should create a user', function () {
auth.createUser(request, response);
var data = JSON.parse(response._getData());
data.username.should.equal('some_user');
});
永远不会通过,因为函数在执行任何操作之前 returning。使用 Mockgoose 模拟 Mongoose,使用 Express-Mocks-HTTP 模拟请求和响应对象。
虽然使用 superagent 和其他请求库相当普遍,但我更愿意单独测试功能,而不是测试整个框架。
有没有办法让测试在评估 should 语句之前等待,而无需将我正在测试的代码更改为 return promises?
您应该使用异步版本的测试,方法是向 it
提供一个带有 done
参数的函数。
有关详细信息,请参阅 http://mochajs.org/#asynchronous-code。
由于您不想修改代码,一种方法是在测试中使用 setTimeout
等待调用完成。
我会尝试这样的事情:
it('Should create a user', function (done) {
auth.createUser(request, response);
setTimeout(function(){
var data = JSON.parse(response._getData());
data.username.should.equal('some_user');
done();
}, 1000); // waiting one second to perform the test
});
(可能有更好的方法)
显然,express-mocks-http 前段时间被废弃了,新的代码在 node-mocks-http 下。使用这个新库,可以使用事件执行我要求的操作。它没有记录,但查看代码你可以弄明白。
创建响应对象时必须传递 EventEmitter 对象:
var EventEmitter = require('events').EventEmitter;
var response = NodeMocks.createResponse({eventEmitter: EventEmitter});
然后,在测试中,您向事件 'end' 或 'send' 添加一个侦听器,因为它们都在调用 res.send 时被触发。 'end' 涵盖的内容超过 'send',以防您有 res.send 以外的呼叫(例如,res.status(404).end().
测试看起来像这样:
it('Should return the user after creation', function (done) {
auth.createUser(request, response);
response.on('send', function () {
var data = response._getData();
data.username.should.equal('someone');
data.email.should.equal('asdf2@asdf.com');
done();
});
});