我正在使用一个数据库库,其基于回调的界面如下所示:
var DB = {
insert: function(options, callback) {
}
}
我想在这个数据库周围实现一个包装器,将其回调样式API转换为基于promise的API。为此,我定义了以下类:
var DatabaseWrapper = {
init: function(db) {
this.db = db;
},
insert: function(options) {
return Q.denodeify(this.db.insert.bind(this.db))(options);
}
}
我想编写一个单元测试,以确保在我致电DatabaseWrapper.insert
时调用DB.insert
。到目前为止,我的测试看起来像这样:
describe('DatabaseWrapper', function () {
var wrapper, insertSpy, bindStub;
beforeEach(function () {
wrapper = Object.create(DatabaseWrapper);
insertSpy = sinon.spy(function () {
console.log('insertSpy got called');
});
bindStub = sinon.stub();
wrapper.db = {
insert: function (options, callback) {
}
};
sinon.stub(wrapper.db.insert, 'bind').returns(insertSpy);
});
describe('#insert', function () {
it('should delegate to db.insert', function (done) {
wrapper.insert({herp: 'derp'});
expect(wrapper.db.insert.bind).to.have.been.calledOnce;
// This fails but I expect it to succeed
expect(promise).to.have.been.calledOnce;
})
});
});
在测试失败后,数据库实例的insert方法实际上被调用,因为在控制台中打印了'insertSpy got called'
消息。
但显然在测试失败后会调用它。
据我所知,这是由于Node process.nextTick
的工作方式。因此,在测试失败后调用回调。有没有办法可以在不依赖第三方库的情况下修复此测试(例如q-flush
)?
答案 0 :(得分:1)
您正在执行异步操作,因此最好执行异步测试。添加setTimeout
仍会使您容易出现竞争条件。
describe('#insert', function () {
it('should delegate to db.insert', function () { // no done here
// note the return here to signal to mocha this is a promise test
return wrapper.insert({herp: 'derp'}).then(function(){
// add expects here, rest of asserts should happen here
expect(wrapper.db.insert.bind).to.have.been.calledOnce;
});
})
});
});