And*_*paw 10 unit-testing mocha.js mongoose
我想将saveMongoose模型可用的方法存根.这是一个示例模型:
/* model.js */
var mongoose = require('mongoose');
var userSchema = mongoose.Schema({
username: {
type: String,
required: true
}
});
var User = mongoose.model('User', userSchema);
module.exports = User;
Run Code Online (Sandbox Code Playgroud)
我有一些将调用该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);
});
};
Run Code Online (Sandbox Code Playgroud)
我想检查一下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)
});
Run Code Online (Sandbox Code Playgroud)
我var saveStub = sinon.stub(mongoose.Model.prototype, 'save')从这里发现了.
一切都很好,除非我尝试添加一些东西给我saveStub,例如saveStub.yields(null).如果我想模拟传递给save回调的错误saveStub.yields('mock error'),我会收到此错误:
TypeError: Attempted to wrap undefined property undefined as function
Run Code Online (Sandbox Code Playgroud)
堆栈跟踪完全没有用.
我做过的研究
我试图重构我的模型来访问底层的用户模型,推荐这里.这给我带来了同样的错误.这是我尝试的代码:
/* in model.js... */
var UserSchema = mongoose.model('User');
User._model = new UserSchema();
/* in test.js... */
var saveStub = sinon.stub(userModel._model, 'save');
Run Code Online (Sandbox Code Playgroud)
我发现这个解决方案对我来说根本不起作用.也许这是因为我以不同的方式设置我的用户模型?
我也试过以下嘲弄本指南和这一个,但比我想象中应该是必要的,让我质疑花费隔离分贝的时间价值的方式更多的设置.
我的印象是,这一切都与猫鼬实现的神秘方式有关save.我已经使用npm阅读了一些关于它的内容hooks,这使得该save方法很难实现.
我也听说过mockgoose,虽然我还没有尝试过这个解决方案.任何人都有这个策略的成功?[编辑:事实证明,mockgoose提供了一个内存数据库,易于设置/拆卸,但它无法解决存根问题.]
任何有关如何解决此问题的见解将非常感激.
这是我开发的最终配置,它使用了sinon和mockery的组合:
// Dependencies
var expect = require('chai').expect;
var sinon = require('sinon');
var mockery = require('mockery');
var reloadStub = require('../../../spec/utils/reloadStub');
describe('UNIT: userController.js', function() {
var reportErrorStub;
var controller;
var userModel;
before(function() {
// mock the error reporter
mockery.enable({
warnOnReplace: false,
warnOnUnregistered: false,
useCleanCache: true
});
// load controller and model
controller = require('./userController');
userModel = require('./userModel');
});
after(function() {
// disable mock after tests complete
mockery.disable();
});
describe('#createUser', function() {
var req;
var res;
var status;
var end;
var json;
// Stub `#save` for all these tests
before(function() {
sinon.stub(userModel.prototype, 'save');
});
// Stub out req and res
beforeEach(function() {
req = {
body: {
username: 'Andrew',
userID: 1
}
};
status = sinon.stub();
end = sinon.stub();
json = sinon.stub();
res = { status: status.returns({ end: end, json: json }) };
});
// Reset call count after each test
afterEach(function() {
userModel.prototype.save.reset();
});
// Restore after all tests finish
after(function() {
userModel.prototype.save.restore();
});
it('should call `User.save`', function(done) {
controller.createUser(req, res);
/**
* Since Mongoose's `new` is asynchronous, run our expectations on the
* next cycle of the event loop.
*/
setTimeout(function() {
expect(userModel.prototype.save.callCount).to.equal(1);
done();
}, 0);
});
}
}
Run Code Online (Sandbox Code Playgroud)
小智 6
你有没有尝试过:
sinon.stub(userModel.prototype, 'save')
Run Code Online (Sandbox Code Playgroud)
另外,在测试中在哪里调用辅助函数?看起来您将函数定义为 utils 模块,但将其作为控制器对象的方法调用。我假设这与该错误消息无关,但它确实使确定存根何时何地被调用变得更加困难。
| 归档时间: |
|
| 查看次数: |
3967 次 |
| 最近记录: |