testing使用SinonJs和Mocha来限制包含Promise Code Block的Route Handler
我有一个restify行动代码块如下:
function retriveAll(req, res, next) { db.user .find({where: {id: 1}) .then(function(user){ res.send(user); }) .catch(function(details){ res.send(details.message); }) .finally(function(){ next(); }); }
我想testing这个动作,具体validationres.send()在这个代码块中被调用 。 稍后validationres.send()返回的数据。 我正在使用SinonJs和Mocha进行testing框架。 以上是上述方法的示例testing代码块。
describe('retrieveAll()', function() { reqStub = {}; resStub = {send: sinon.stub()}; nextStub = sinon.stub(); beforeEach(function() { module.retrieveAll(reqStub, resStub, nextStub); }); // this doesn't work // and the sub.calledCount is 0 // i wonder if it's because the res.send() is inside a Promise code block??? // if I move the res.send() out from Promise, just before next(), then it works it('should call res.send()', function() { sinon.assert.calledOnce(resStub.send); }); // this one works it('should call next', function() { sinon.assert.calledOnce(nextStub); }); });
有人可以解释一下吗?
beforeEach()
的callback函数接收一个done
参数,可以调用这个参数来表示一个asynchronous完成。 由于您的retriveAll
函数将最后一个参数( next
)作为最后一个操作,所以您可以将该参数作为next
值传递,它应该可以工作:
beforeEach(function(done) { module.retrieveAll(reqStub, resStub, done); });
然而,你会松动下一个nextStub
,所以…或者,你可以窥探那个done
function:
describe('retrieveAll()', function() { var reqStub = {}; var resStub = {send: sinon.stub()}; var nextSpy; beforeEach(function(done) { nextSpy = sinon.spy(done); module.retrieveAll(reqStub, resStub, done); }); // this doesn't work // and the sub.calledCount is 0 // i wonder if it's because the res.send() is inside a Promise code block??? // if I move the res.send() out from Promise, just before next(), then it works it('should call res.send()', function() { sinon.assert.calledOnce(resStub.send); }); // this one works it('should call next', function() { sinon.assert.calledOnce(nextSpy); }); });
所以,我得到了这个工作感谢@Amit指向我beforeEach
done
callback
首先 ,我修改了retrieveAll
以便next
callback包含在promise链中。 我把它放在finally
处理程序中,确保next
将在所有进程之后被调用。
其次 ,我把这个done
了,然后nextStub
会监视done
callback。
第三 ,而不是将done
CB传递给module.v1.retrieveAll
我使用nextStub
。 这解决了testingnextStub.calledOnce
的问题。
现在更新的代码看起来像:
function retriveAll(req, res, next) { db.user .find({where: {id: 1}) .then(function(user){ res.send(user); }) .catch(function(details){ res.send(details.message); }) .finally(function(){ next(); }); }
describe('retrieveAll()', function() { var reqStub = {}; var resStub = {send: sinon.stub()}; var nextStub; beforeEach(function(done) { nextStub = sinon.spy(done); module.retrieveAll(reqStub, resStub, nextStub); }); // this doesn't work // and the sub.calledCount is 0 // i wonder if it's because the res.send() is inside a Promise code block??? // if I move the res.send() out from Promise, just before next(), then it works it('should call res.send()', function() { sinon.assert.calledOnce(resStub.send); }); // this one works it('should call next', function() { sinon.assert.calledOnce(nextStub); }); });
我会select@Amit答案作为最好的答案,因为他帮助并给我线索的变化。