javascript - Stubbing a function in sinon to return different value every time it is called -
i have function shown below:
function test(parms) { var self = this; return this.test2(parms) .then(function (data) { if (data) { return ; } else { return bluebird.delay(1000) .then(self.test.bind(self, parms)); } }.bind(self)); }; i trying write unit tests function. using sinon.stub mock functionality of function test2.
i wrote test case test2 returns true , therefore test function completes execution. want test case on first instance test2 returns false, waits delay , next time test2 returns true. wrote test case below:
var clock; var result; var test2stub; var count = 0; before(function () { clock = sinon.usefaketimers(); //object defined before test2stub = sinon.stub(object,"test2", function () { console.log("count is: " + count); if (count === 0) { return (bluebird.resolve(false)); } else if (count === 1) { return (bluebird.resolve(true)); } }); clock.tick(1000); object.test("xyz") .then(function (data) { result = data; }); clock.tick(1000); count = count + 1; clock.tick(1000); }); after(function () { test2stub.restore(); clock.restore(); }); it("result should undefined. check if test2 returned false first & true next", function () { expect(result).to.be.undefined; }); in logs shows count has value 0 only.
the code of
testincorrect. never returns data on success. returnsundefined. function should return data on success otherwise won't able use parameter next.thenhandler.then(function (data) { if (data) { return data; }next make wrong assumptions function
test. never returnundefined. function rather dangerous , call forever in endless chain of promises until squeezes out not-null datatest2.one shouldn't launch test code in
beforeorbeforeeachsection.before,aftermeant prepare environment faking timers , restoring them.
1 reason calling tested code inithandler because promises should handled differently. handler should accept parameter indicates test asynchronous , the test engine gives timeout (usually 10 secs) complete. test expected either calldone()indicate test successful or calldone(error)if failed , thereerrorobject (orexpectthrew exception).
should move fake timer after async operation started. in code firstclock.tickuseless.there trick using
faketimers. can move time manually doesn't move on own. first tick works well. promise executed. upon returning.delay(1000)promise, there no command move time forward. so, finish test correctly (not modify tested code) have stubbluebird.delay
i change stubs implementation , this
describe("test2", function(){ beforeeach(function(){ clock = sinon.usefaketimers(); test2stub = sinon.stub(object,"test2", function () { console.log("count is: " + count); return (bluebird.resolve((count++) > 0)); }); var _delay = bluebird.delay.bind(bluebird); bluebirddelaystub = sinon.stub(bluebird,"delay", function (delay) { var promise = _delay(delay); clock.tick(1000); return promise; }); }) it("should return true", function (done) { object.test("xyz") .then(function (data) { expect(data).to.be.true; expect(count).to.equal(2); done(); }) .catch(function(err){ done(err); }); clock.tick(1000); }); after(function () { test2stub.restore(); clock.restore(); bluebirddelaystub.restore(); }); }) ps verified code under node.js 0.10.35 , bluebird 2.9.34
Comments
Post a Comment