Search code examples
node.jspromisebluebirdsinonrestify

Testing Restify Route Handler that contains Promise Code Block, using SinonJs and Mocha


I have a restify action code block below:

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();
        });
    }

I want to test this action specifically validating that res.send() was called within this code block. And later on validating the res.send() returned data. I'm using SinonJs and Mocha for testing framework. Here's a sample test code block for the method above.

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);
    });
});

Could someone shed some light?


Solution

  • The beforeEach()'s callback function receives a done parameter that can be called to signal an asynchronous completion. Since your retriveAll function calls the last parameter (next) as the last action, you can pass that parameter as the next value and it should work:

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

    You will however loose the nextStub, so... alternatively, you could spy on that 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);
        });
    });