我在理解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代码才能弄清楚这个。
答案 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设置为它自己的变量允许你保持一个句柄,直到调用超时。