【发布时间】:2015-05-03 16:10:55
【问题描述】:
我想对 Mongoose 模型可用的 save 方法存根。这是一个示例模型:
/* model.js */
var mongoose = require('mongoose');
var userSchema = mongoose.Schema({
username: {
type: String,
required: true
}
});
var User = mongoose.model('User', userSchema);
module.exports = User;
我有一些辅助函数会调用save 方法。
/* utils.js */
var User = require('./model');
module.exports = function(req, res) {
var username = req.body.username;
var user = new User({ username: username });
user.save(function(err) {
if (err) return res.end();
return res.sendStatus(201);
});
};
我想检查 user.save 是否在我的辅助函数中使用单元测试被调用。
/* test.js */
var mongoose = require('mongoose');
var createUser = require('./utils');
var userModel = require('./model');
it('should do what...', function(done) {
var req = { username: 'Andrew' };
var res = { sendStatus: sinon.stub() };
var saveStub = sinon.stub(mongoose.Model.prototype, 'save');
saveStub.yields(null);
createUser(req, res);
// because `save` is asynchronous, it has proven necessary to place the
// expectations inside a setTimeout to run in the next turn of the event loop
setTimeout(function() {
expect(saveStub.called).to.equal(true);
expect(res.sendStatus.called).to.equal(true);
done();
}, 0)
});
我从here 发现了var saveStub = sinon.stub(mongoose.Model.prototype, 'save')。
除非我尝试向我的 saveStub 添加一些内容,否则一切都很好,例如与saveStub.yields(null)。如果我想用saveStub.yields('mock error') 模拟传递给save 回调的错误,我会收到以下错误:
TypeError: Attempted to wrap undefined property undefined as function
堆栈跟踪完全没有帮助。
我所做的研究
按照here 的建议,我尝试重构我的模型以访问底层用户模型。这对我产生了同样的错误。这是我尝试的代码:
/* in model.js... */
var UserSchema = mongoose.model('User');
User._model = new UserSchema();
/* in test.js... */
var saveStub = sinon.stub(userModel._model, 'save');
我发现this solution 根本不适合我。也许这是因为我以不同的方式设置我的用户模型?
我还尝试了在 this guide 和 this one 之后的 Mockery,但这比我认为的需要的设置要多得多,这让我质疑花时间隔离数据库的价值。
我的印象是,这一切都与猫鼬实现save 的神秘方式有关。我已经使用 npm hooks 阅读了一些关于它的内容,这使得 save 方法很容易存根。
我也听说过mockgoose,虽然我还没有尝试过那个解决方案。有人用这个策略成功了吗? [编辑:事实证明 mockgoose 提供了一个内存数据库以便于设置/拆卸,但它并没有解决存根问题。]
任何有关如何解决此问题的见解将不胜感激。
【问题讨论】:
标签: unit-testing mongoose mocha.js