Supertest和Mongoose中间件(删除后)

时间:2015-06-08 02:14:12

标签: express mongoose mocha chai supertest

我已经习惯了这几天,我无法弄清楚为什么没有调用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);

2 个答案:

答案 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时,通常会使服务器保持运行,因此可以完成后期作业。

现在,出现了一个问题:我们如何能够一致地测试后挂钩?我提出这个问题是因为我正在寻找解决方案。如果您已经有答案,请在此处发帖。