用Mongoosetestingasynchronous中间件function

我正在Mongoose中使用一个save中间件来在数据库中创build一个活动日志,只要采取一些行动。 就像是

 UserSchema.post("save", function (doc) { mongoose.model("Activity").create({activity: "User created: " + doc._id}); }); 

这似乎工作正常,但问题是,我不能testing它,因为没有办法传递一个callback post (这可能没有意义)。 我用mochatesting了这一点:

 User.create({name: "foo"}, function (err, user) { Activity.find().exec(function (err, act) { act[0].activity.should.match(new RegExp(user._id)); done(); }); }); 

问题是,调用.find之前, Activity.create显然没有完成。 我可以通过在setTimeout包装.find来解决这个问题,但是这对我来说似乎很.find 。 有什么方法可以testingasynchronousmongoose中间件操作?

不幸的是,没有办法以你喜欢的方式可靠地插入这两个asynchronous函数(因为没有线程,你不能“暂停”执行)。 他们可以以不一致的顺序完成,这就给你解决scheme,如超时。

我build议你把一个事件处理程序连接到Activity类,这样当Activity被写入/失败时,它会查看应该被logging的排队(散列?)活动列表。 所以,当一个活动创build时,添加到列表( "onactivitycreated") 。 然后,它最终会写( "onactivitywritten" ),比较和删除成功可能(不知道什么是有道理的摩卡)。 当你的testing完成后,你可以看到列表是否为空。

你可以使用util.inherits(Activity, EventEmitter)来扩展Activity类的事件function。

现在,你仍然需要在列表上等待/超时,如果有事件没有处理失败,你也需要处理。

编辑 – 忽略下面的build议作为一个有趣的演示asynchronous,不会为你工作。 🙂

如果你想testing它们,我会看看像asynchronous这样的库,你可以在一系列(或在这种情况下, waterfall )执行你的代码,这样你可以先创build一个User ,然后,一旦它完成后,validation是否logging了正确的Activity 。 我在这里使用了waterfall ,以便值可以从一个任务传递到下一个。

 async.waterfall([ function(done) { User.create({name: "foo"}, function (err, user) { if (err) { done(err); return; } done(null, user._id); // 2nd param sent to next task as 1st param }); }, function(id, done) { // got the _id from above // substitute efficient method for finding // the corresponding activity document (maybe it's another field?) Activity.findById(id, function (err, act) { if (err) { done(err); return; } if (act) { done(null, true); done(null, false); // not found?! }); } ], function(err, result) { console.log("Success? " + result); }); 

asynchronous后保存中间件显然将在Mongoose 4.0.0中可用:

https://github.com/LearnBoost/mongoose/issues/787

https://github.com/LearnBoost/mongoose/issues/2124

现在,您可以通过在文档上修补save方法来解决此问题,以便它支持asynchronous后保存中间件。 以下代码正在为您处理类似的情况。

 // put any functions here that you would like to run post-save var postSave = [ function(next) { console.log(this._id); return next(); } ]; var Model = require('mongoose/lib/model'); // monkey patch the save method FooSchema.methods.save = function(done) { return Model.prototype.save.call(this, function(err, result) { if (err) return done(err, result); // bind the postSave functions to the saved model var fns = postSave.map(function(f) {return f.bind(result);}); return async.series(fns, function(err) {done(err, result);} ); }); };