Qunit + SinonJs spy.calledOnce在setTimeout中是未定义的

时间:2012-12-25 15:45:11

标签: javascript qunit sinon

我在理解sinonjs间谍的行为时遇到了问题。

这是我的测试:

asyncTest('sinon async spies test', 
function() { 

    var pApi = 
    { 
        product: function(id, options) { 
            var d = { o: 'a result' };
            options.success(d);
            return d;
        },
    };

    this.spy(pApi, 'product');
    pApi.product(1, { success: function(data) {} });

    //Assertion 1
    ok(pApi.product.calledOnce, 'product API called: ' + 
        pApi.product.calledOnce);

    setTimeout(
            function() { 
                //Assertion 2
                ok(pApi.product.calledOnce, 
                    'product function called once (calledOnce: ' +   
                     pApi.product.calledOnce + ')');
                start();
            }, 1000);

});

使用qunit和sinonjs(通过sinon-qunit)运行上述测试,我传递Assertion 1但是失败了Assertion 2(在setTimeout回调中)。实际上,当我们在控制台中记录pApi.product.calledOnce的值时(通过断言的消息完成),它是undefined

注意:我在测试文件的顶部有这个:

sinon.config.useFakeTimers = false;

有人能解释这种奇怪的行为吗?在setTimeout回调中不应该pApi.product并且两者都没有calledOnce作为间谍的有效属性吗?

更新

基于http://api.qunitjs.com/asyncTest/,我弄清楚了为什么会显示上述行为。

在调用asyncTest函数之前,

start()不运行testrunner。当我将this.spy(pApi, 'product')更改为sinon.spy(pApi, 'product')时,上述测试有效。显然,依赖于是否使用test而不是asyncTest,这会影响this.spy方法运行的时间。

需要实际查看sinon,qunit和sinon-qunit代码才能弄清楚这个。

1 个答案:

答案 0 :(得分:2)

您应该将间谍分配给变量,并使用它来断言calledOnce:

asyncTest('sinon async spies test', function() { 
    var pApi = { 
        product: function(id, options) { 
            var d = { o: 'a result' };
            options.success(d);
            return d;
        }
    };

    var pApiSpy = this.spy(pApi, 'product');
    pApi.product(1, { success: function(data) {} });

    //Assertion 1
    ok(pApiSpy.calledOnce, 'product API called');

    setTimeout(
            function() { 
                //Assertion 2
                ok(pApiSpy.calledOnce, 
                    'product function called once');
                start();
            }, 1000);

});

这将传递两个断言。我认为问题与Sinon在测试函数结束时恢复方法有关,即使QUnit仍在等待start()指示测试完成。调用超时函数时,pApi.product不再是间谍对象,因此它没有callOnce属性。将spy设置为它自己的变量允许你保持一个句柄,直到调用超时。