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
test
incorrect. never returns data on success. returnsundefined
. function should return data on success otherwise won't able use parameter next.then
handler.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
before
orbeforeeach
section.before
,after
meant prepare environment faking timers , restoring them.
1 reason calling tested code init
handler 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 , thereerror
object (orexpect
threw exception).
should move fake timer after async operation started. in code firstclock.tick
useless.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