使用SinonJs和Mocha

时间:2015-09-01 20:50:27

标签: node.js promise bluebird sinon restify

我在下面有一个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);
    });
});

有人可以解释一下吗?

2 个答案:

答案 0 :(得分:2)

beforeEach()的回调函数接收done参数,可以调用该参数来表示异步完成。由于您的retriveAll函数调用最后一个参数(next)作为最后一个操作,因此您可以将该参数作为next值传递,它应该有效:

beforeEach(function(done) {
    module.retrieveAll(reqStub, resStub, done);
});

但是你会松开nextStub,所以......或者,你可以<{1}}函数间谍

done

答案 1 :(得分:1)

所以,我感谢 @Amit 指导我done上的beforeEach回调

首先,我修改了retrieveAll,因此next回调包含在承诺链中。我把它放在finally处理程序中,确保在所有进程后调用next

第二次,我将done传递给beforeEach,然后nextStub会监视done回调。

第三次,而不是将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答案作为最佳答案,因为他帮助并提供了有关变化的线索。