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 前端调用时,这个钩子被调用得非常好。但是,当我 运行 使用 supertestchaimocha 进行测试时未被调用。这是我的测试代码:

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。