每次调用时,在sinon中扼杀函数返回不同的值

我有一个function如下所示:

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

我正在为这个函数编写unit testing。 我正在使用sinon.stub来模拟函数test2的function。

我写了一个testing用例,其中test2返回true ,因此test函数成功完成执行。 不过,我想要一个testing用例,在第一个实例test2返回false ,它等待延迟,下次test2返回true 。 为此我写了我的testing用例如下:

 var clock; var result; var test2stub; var count = 0; before(function () { clock = sinon.useFakeTimers(); //object is 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 be undefined. Check if test2 returned false first & true next", function () { expect(result).to.be.undefined; }); 

在日志中显示计数值只有0。

  1. test代码实际上是不正确的。 它永远不会返回成功的数据。 它返回undefined 。 该函数应该返回成功的数据,否则你将无法使用它作为下一个.then处理程序的参数

     .then(function (data) { if (data) { return data; } 
  2. 接下来你对functiontest做出错误的假设。 它永远不会返回undefined 。 这个函数是相当危险的,并且会在永无止境的承诺链中永远自称,直到从test2排除任何非空数据为止。

  3. beforeEach部分beforebefore不应该启动testing代码。 beforeafter都是为了准备像伪造定时器然后恢复它们的环境。
    在处理程序中调用testing代码的一个原因是因为承诺应该以不同的方式处理。 处理程序应该接受一个参数,表明testing是asynchronous的,testing引擎会给它一个超时(通常是10秒)来完成。 testing预计要么调用done()来指示testing是成功的,要么调用done(error)如果失败并且存在error对象(或者expect抛出exception)。
    你也应该在asynchronous操作开始之后移动假定时器。 在你的代码中,第一个clock.tick是无用的。

  4. 有一个使用fakeTimers的技巧。 您可以手动移动时间,但不能自行移动。 对于第一个勾号它运作良好。 承诺被执行。 然而,在返回。 .delay(1000)承诺之后,将没有命令将时间推进。 因此,为了正确地完成testing(不要修改testing代码),您还需要存根Bluebird.delay

我会改变存根实现,并做这样的事情

 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 eventually 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我validation了这个代码在Node.js 0.10.35和蓝鸟2.9.34