Supertest 和 Mongoose 中间件(post 移除)
Supertest and Mongoose Middleware (post remove)
这几天我一直在摆弄这个,我想不通为什么没有调用 Mongoose 中间件。
所以我在 node.js 中有一个 API,并且我有一个使用 Angular.js 的网站。猫鼬中间件是这样的:
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);
这是我的建议。让我们对 #findOne
找到的文档执行 #remove
。如果我没记错的话,删除 post 钩子只适用于 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);
});
});
});
Mongoose post 挂钩 运行 在操作完成后,同时进行操作回调。请参阅以下评论:
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 挂钩 运行 独立于服务器响应的进程。当您 运行 测试时,服务器会在测试完成后立即关闭,并且可能没有足够的时间来完成 post 挂钩。另一方面,当您从客户端调用 API 时,通常您保持服务器 运行ning,因此 post 作业可以完成。
现在,问题来了:我们如何才能一致地测试 post 钩子?我提出这个问题是因为我正在寻找解决方案。如果您已经有了答案,请在此处 post。
这几天我一直在摆弄这个,我想不通为什么没有调用 Mongoose 中间件。
所以我在 node.js 中有一个 API,并且我有一个使用 Angular.js 的网站。猫鼬中间件是这样的:
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);
这是我的建议。让我们对 #findOne
找到的文档执行 #remove
。如果我没记错的话,删除 post 钩子只适用于 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);
});
});
});
Mongoose post 挂钩 运行 在操作完成后,同时进行操作回调。请参阅以下评论:
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 挂钩 运行 独立于服务器响应的进程。当您 运行 测试时,服务器会在测试完成后立即关闭,并且可能没有足够的时间来完成 post 挂钩。另一方面,当您从客户端调用 API 时,通常您保持服务器 运行ning,因此 post 作业可以完成。
现在,问题来了:我们如何才能一致地测试 post 钩子?我提出这个问题是因为我正在寻找解决方案。如果您已经有了答案,请在此处 post。