Javascript 在sinon中存根函数,以便每次调用时返回不同的值
我有一个如下所示的功能:Javascript 在sinon中存根函数,以便每次调用时返回不同的值,javascript,node.js,unit-testing,sinon,Javascript,Node.js,Unit Testing,Sinon,我有一个如下所示的功能: function test(parms) { var self = this; return this.test2(parms) .then(function (data) { if (data) { return ; } else { return Bluebird.delay(1000
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));
};
我正在尝试为此函数编写单元测试。我正在使用sinon.stub
模拟函数test2
的功能
我编写了一个测试用例,其中test2
返回true
,因此test
函数成功地完成了执行。然而,我想要一个测试用例,在第一个实例中test2
返回false
,它等待延迟,下一次test2
返回true
。为此,我编写了以下测试用例:
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;
});
在日志中,它显示count的值仅为0
测试的代码实际上不正确。它从不返回成功的数据。它返回未定义的
。函数应在成功时返回数据,否则您将无法将其用作下一个处理程序的参数
.then(function (data) {
if (data) {
return data;
}
测试做出了错误的假设。它永远不会返回未定义的
。这个函数相当危险,它会在无尽的承诺链中永远调用自己,直到它从test2
中挤出任何非空数据
中启动测试代码<“代码>之前”
和“代码>之后”旨在为环境做准备,比如伪造计时器,然后还原它们。在
it
处理程序中调用测试代码的一个原因是,承诺应该以不同的方式处理。处理程序应该接受一个参数,该参数指示测试将是异步的,并且测试引擎给它一个超时(通常为10秒)来完成。测试需要调用done()
以指示测试成功,或者调用done(error)
,如果测试失败并且存在错误
对象(或者expect
引发异常)。此外,您应该在异步操作启动后移动假计时器。在你的代码中,第一个
时钟实际上是无用的
.delay(1000)
promise时,将不会有命令将时间向前移动。因此,要正确完成测试(而不是修改测试代码),您还必须存根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我在Node.js 0.10.35和Bluebird 2.9.34下验证了这段代码@Kinil谢谢大家!你写时钟的原因是什么?勾选(2000)而不是1000?检查更新后的答案。我希望它能触发两个承诺(每1000毫秒一次),但我怀疑这是一个陷阱,并且我验证了Node.js中的代码。为什么您还要中断Bluebird的延迟函数?时钟滴答声不会自动影响延迟函数的时间吗?也许我在第4节中解释得不太清楚。使用
fakeTimers时
每次都应手动移动时间以触发超时。因此,在调用Bluebird.delay
之后,必须有执行clock.tick
的代码。否则,您会注意到这样一种情况:控制台中只有一个count=0
的登录,因为.delay
永远不会解析和。然后
再也不会调用test
。还有另一种选择。不要使用fakeTimers
,但是这是一种不好的方法,因为您将有一个需要2000毫秒的单元测试。总是会有警告,并且测试将花费太长的时间