每次调用时,在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。
-
test
代码实际上是不正确的。 它永远不会返回成功的数据。 它返回undefined
。 该函数应该返回成功的数据,否则你将无法使用它作为下一个.then
处理程序的参数.then(function (data) { if (data) { return data; }
-
接下来你对function
test
做出错误的假设。 它永远不会返回undefined
。 这个函数是相当危险的,并且会在永无止境的承诺链中永远自称,直到从test2
排除任何非空数据为止。 -
beforeEach
部分before
或before
不应该启动testing代码。before
和after
都是为了准备像伪造定时器然后恢复它们的环境。
在处理程序中调用testing代码的一个原因是因为承诺应该以不同的方式处理。 处理程序应该接受一个参数,表明testing是asynchronous的,testing引擎会给它一个超时(通常是10秒)来完成。 testing预计要么调用done()
来指示testing是成功的,要么调用done(error)
如果失败并且存在error
对象(或者expect
抛出exception)。
你也应该在asynchronous操作开始之后移动假定时器。 在你的代码中,第一个clock.tick
是无用的。 -
有一个使用
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