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()返回的数据。 我正在使用SinonJsMocha进行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 ,所以…或者,你可以窥探那个donefunction:

 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 donecallback

首先 ,我修改了retrieveAll以便nextcallback包含在promise链中。 我把它放在finally处理程序中,确保next将在所有进程之后被调用。

其次 ,我把这个done了,然后nextStub会监视donecallback。

第三 ,而不是将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答案作为最好的答案,因为他帮助并给我线索的变化。