Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在sinon中存根函数,以便每次调用时返回不同的值_Javascript_Node.js_Unit Testing_Sinon - Fatal编程技术网

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
    引发异常)。
    此外,您应该在异步操作启动后移动假计时器。在你的代码中,第一个
    时钟实际上是无用的

  • 使用fakeTimers有一个技巧。您可以手动移动时间,但它不会自行移动。对于第一个滴答声,它工作得很好。诺言已兑现。但是,在返回
    .delay(1000)
    promise时,将不会有命令将时间向前移动。因此,要正确完成测试(而不是修改测试代码),您还必须存根
    Bluebird.delay

  • 我将更改stubs实现并执行类似的操作

    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毫秒的单元测试。总是会有警告,并且测试将花费太长的时间