测试IIFE(立即调用的函数表达式)的最佳方法是使用setTimeout
递归调用自身:
(function myFuncToBeTested() {
// Code to be tested
...
setTimeout(myFuncToBeTested, timeout) // timeout should be checked
})()
我发现以下解决方案用setTimeout
存根替换全局own
函数。这有以下问题:
// Saving original setTimeout. This should be restored in test cleanup
originalSetTimeout = global.setTimeout
// Replace with function
global.setTimeout = function setImmediate(myFunc, interval) {
// FIXME: This function now always called
// Save interval to be tested
savedInterval = interval
}
答案 0 :(得分:3)
可以将此功能变成对象吗?
var myObject = (function(){
function start(){
myFuncToBeTested();
setTimeout(start, 10);
return this;
}
function myFunctToBeTested(){
//Code to be tested
}
return {
start: start,
myFuncToBeTested: myFuncToBeTested
}
})().start();
然后您可以使用您选择的测试框架进行测试:
assert( myObject.myFuncToBeTested() == expectedValue );
答案 1 :(得分:1)
我想建议在thedarklord47的答案和你的实验之间使用存根setTimeout
进行混合解决方案。像你这样的IIFE本来就很难测试,因为你没有留下任何方法来检查它是否被调用。您可以按如下方式修改API:
var repeater = {
start: function () {
this.func();
setTimeout(this.start.bind(this), timeout);
},
func: function () {
// code to be tested
}
};
然后你的测试看起来像这样(因为你标记了sinon我已经使用过它,特别是它的伪计时器API,它可以让你检查你的间隔功能):
// setup
var clock = sinon.useFakeTimers();
var spy = sinon.spy(repeater, 'func');
// test
repeater.start();
assert(spy.calledOnce);
// advance clock to trigger timeout
clock.tick(timeout);
assert(spy.calledTwice);
// advance clock again
clock.tick(timeout);
assert(spy.calledThrice);
// teardown
clock.restore();
spy.restore();