make javascript function callback-ish

我正在使用jquery的javascript函数:

my.namespace.loadSomeStuff = function() { $.get('/Services/loadStuff', function(c){ $("#stuffDiv").html(c); }); }; 

我正在尝试为此编写unit testing。

现在,因为这个函数并没有真正返回任何东西并使用jquery的’get’异步加载一些东西我很难测试它。

基本上我想做的是调用这个函数,等到它返回一些东西,然后访问加载的元素来validation…类似于:

 my.namespace.loadSomeStuff(function(){ alert('boo'); assertSame('Login', $("#stuffDiv").find(......); }); 

现在,我在调用unit testing的模板中创建了一个,它将正确加载和显示,但警报或断言永远不会执行。

我有没有办法在不增加大量额外代码的情况下实现这一目标?

谢谢

你必须在loadSomeStuff方法中添加一个参数来接收你在示例代码中调用的回调函数,然后故意调用它:

 my.namespace.loadSomeStuff= function(callback) { $.get('/Services/loadStuff', function(c){ $("#stuffDiv").html(c); if (callback!==undefined) callback(); }); }; 

我不确定仅仅为了支持unit testing而使代码更复杂是值得的,尽管你可能会认为向异步函数添加回调是通用的有用性。

另一种方法是使测试使用粗略的超时。

您可以使用Nick提到的ajaxSuccess (可能结合超时和/或捕获ajaxError ?)。 但令我印象深刻的是,这可能会增加一些unit testing的实施知识。 如果loadSomeStuff将来在没有XMLHttpRequest的情况下更改,或者有时仅在没有缓存时使用它,该怎么办? 然后unit testing就会中断。 当然,你可以更新测试以匹配实现,但那不是真正有用的unit testing,是吗?

您可以使用全局AJAX事件 ,例如:

 $(document).ajaxSuccess(function() { assertSame('Login', $("#stuffDiv").find(......)); }); 

ajaxSuccess将在每个 AJAX请求之后发生,如果你想在所有同步请求完成后运行一个事件,那么ajaxStop就是你所追求的。 这两个处理程序不必直接附加到您的AJAX方法 ,它们可以在unit testing中完成。

这些是正常事件( 此处为完整列表 ),因此您可以根据需要使用.bind() / .unbind() ,例如,当完成上述unit testing时:

 $(document).ajaxSuccess(function() { assertSame('Login', $("#stuffDiv").find(......)); $(this).unbind('ajaxSuccess'); //cleanup });