使用 SinonJs 和 Mocha 测试包含 Promise 代码块的 Restify 路由处理程序
Testing Restify Route Handler that contains Promise Code Block, using SinonJs and Mocha
我在下面有一个 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();
});
}
我想测试这个动作,专门验证 res.send() 是在这个代码块 中调用的。稍后验证 res.send() 返回的数据。我正在使用 SinonJs 和 Mocha 来测试框架。这是上述方法的示例测试代码块。
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()
的回调函数接收一个 done
参数,可以调用该参数来表示异步完成。由于您的 retriveAll
函数调用最后一个参数 (next
) 作为最后一个操作,您可以将该参数作为 next
值传递,它应该可以工作:
beforeEach(function(done) {
module.retrieveAll(reqStub, resStub, done);
});
但是你会松开 nextStub
,所以...或者,你可以 spy 那个 done
函数:
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
回调
首先,我修改了retrieveAll
所以next
回调包含在承诺链中。我把它放在 finally
处理程序中,确保 next
将在所有过程之后被调用。
第二个,我将done
传递给beforeEach
,然后nextStub
将监视done
回调。
Third,我没有将 done
cb 传递给 module.v1.retrieveAll
,而是使用了 nextStub
。这解决了测试 nextStub.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);
});
});
我将选择@Amit 的答案作为最佳答案,因为他帮助了我并为我提供了有关更改的线索。
我在下面有一个 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();
});
}
我想测试这个动作,专门验证 res.send() 是在这个代码块 中调用的。稍后验证 res.send() 返回的数据。我正在使用 SinonJs 和 Mocha 来测试框架。这是上述方法的示例测试代码块。
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()
的回调函数接收一个 done
参数,可以调用该参数来表示异步完成。由于您的 retriveAll
函数调用最后一个参数 (next
) 作为最后一个操作,您可以将该参数作为 next
值传递,它应该可以工作:
beforeEach(function(done) {
module.retrieveAll(reqStub, resStub, done);
});
但是你会松开 nextStub
,所以...或者,你可以 spy 那个 done
函数:
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
回调
首先,我修改了retrieveAll
所以next
回调包含在承诺链中。我把它放在 finally
处理程序中,确保 next
将在所有过程之后被调用。
第二个,我将done
传递给beforeEach
,然后nextStub
将监视done
回调。
Third,我没有将 done
cb 传递给 module.v1.retrieveAll
,而是使用了 nextStub
。这解决了测试 nextStub.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);
});
});
我将选择@Amit 的答案作为最佳答案,因为他帮助了我并为我提供了有关更改的线索。