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

我的未来我决定 提交于 2019-12-23 00:48:08

问题


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?


回答1:


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



回答2:


So, I got this working thanks for @Amit for pointing me to the done callback on beforeEach

First, I modified the retrieveAll so the next callback is included in the promise chain. I put it in the finally handler making sure that next will be called after all process.

Second, I passed the done to beforeEach and then nextStub will spy on done callback.

Third, instead of passing done cb to module.v1.retrieveAll I used nextStub. This solve the issue on testing nextStub.calledOnce.

The updated code now looks:

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

I going to choose @Amit answer as best answer since he helped and gave me clues on the changes.



来源:https://stackoverflow.com/questions/32340667/testing-restify-route-handler-that-contains-promise-code-block-using-sinonjs-an

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!