我已经习惯了这几天,我无法弄清楚为什么没有调用Mongoose中间件。
所以我在node.js中有一个API,我有一个使用Angular.js的网站。 Mongoose中间件是这样的:
schema.post('remove', function (doc) {
console.log('doctors - post - remove');
});
因此,当从Angular前端调用时,此钩子被称为完全正常。但是,当我使用 supertest , chai 和 mocha 进行测试时,不会调用该挂钩。这是我的测试代码:
it('/doctors - POST - (create doctor)', function(done){
request(app)
.post('/doctors')
.send(doctor)
.end(function (err, res){
if (res.body['error']) {
expect(S(res.body['error']).startsWith('doctor already exists')).to.be.true;
}
else
expect(res.body['email']).to.equal(doctor['email']);
done();
});
});
....
it('/doctors/remove - DELETE', function(done){
request(app)
.del('/doctors/remove')
.auth(new_doctor_creds["email"], new_doctor_creds["pass"])
.end(function (err, res){
expect(Object.keys(res.body).length).to.not.equal(0);
done();
});
});
这是我的快递应用程序的路线:
app.delete('/doctors/remove', authController.isAuthenticated, function (req, res, next) {
var email = req.user['email'];
Doctors.findOne({email:email}).remove(function (err, removed) {
if (err) return next(err);
return res.status(200).send(removed);
});
});
同样,当从Angular应用程序的API调用调用时,这个Mongoose中间件工作得很好。但是,在使用supertest进行测试时,它不起作用。关于该怎么做的任何想法?
编辑:我尝试使用简化版本重新创建此示例,以便您可以看到所有代码。所以这是一个两个文件版本仍然无法正常工作。这是app.js:
var mongoose = require('mongoose');
var app = require('express')();
var http = require('http');
var fs = require('fs');
var Doctors = require('./schema');
mongoose.connect('mongodb://localhost/m4', function(err) {
if (err) throw err;
console.log('connected');
app.get('/post', function (req, res, next) {
console.log('create');
Doctors.create({email:"hello"}, function (err, inserted) {
if (err) console.log(err);
res.end();
});
});
app.get('/delete', function (req, res, next) {
console.log('removed');
Doctors.remove({email:"hello"}, function (err, removed) {
if (err) console.log(err);
res.end();
});
});
http.createServer(app).listen('6000', function () {
console.log('now listen on localhost:6000');
});
});
和架构:
var mongoose = require('mongoose');
var schema = mongoose.Schema({
email: { type: String }
});
schema.pre('save', function (next) {
console.log('doctors - post - save');
next();
});
schema.post('remove', function (doc) {
console.log('doctors - post - remove');
});
module.exports = mongoose.model('Doctors', schema);
答案 0 :(得分:2)
这是我的建议。让我们对#remove
找到的文档执行#findOne
。如果我没记错的话,删除帖子后挂钩只适用于Doc#remove
,而不适用于Model#remove
。
schema.post('remove', function (doc) {
console.log('doctors - post - remove'); // <-- now runs
});
app.delete('/doctors/remove', authController.isAuthenticated, function (req, res, next) {
var email = req.user['email'];
Doctors.findOne({email: email}, function(err, doc) {
if (err) {
return next(err);
}
doc.remove().then(function(removed) {
return res.status(200).send(removed);
}, function(err) {
next(err);
});
});
});
答案 1 :(得分:0)
Mongoose post hooks在操作完成后运行,与操作回调同时运行。请参阅以下评论:
Doctors.findOne({email:email}).remove(function (err, removed) {
// All this code and the post hook are executed at the same time
if (err) return next(err);
// Here you send the response so supertest#end() will be triggered
// It's not guaranteed that post remove was executed completely at this point
return res.status(200).send(removed);
});
使后挂钩运行独立于服务器响应的进程。当您运行测试时,服务器在测试完成后立即关闭,并且可能没有足够的时间来完成post挂钩。另一方面,当您从客户端调用API时,通常会使服务器保持运行,因此可以完成后期作业。
现在,出现了一个问题:我们如何能够一致地测试后挂钩?我提出这个问题是因为我正在寻找解决方案。如果您已经有答案,请在此处发帖。