make javascript function callback-ish

时间:2010-07-06 10:45:17

标签: javascript jquery unit-testing callback

我使用jquery有一个javascript函数:

my.namespace.loadSomeStuff = function() {

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

我正在尝试为此编写单元测试。

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

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

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

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

有没有办法可以做到这一点,而不需要为我拥有的每一个函数添加大量的额外代码?

感谢 吨

2 个答案:

答案 0 :(得分:1)

您可以使用the global AJAX events for this,例如:

$(document).ajaxSuccess(function() {
  assertSame('Login', $("#stuffDiv").find(......));
});
ajaxSuccess将在每个 AJAX请求之后发生,如果您想要在所有同步请求完成后运行的事件,那么ajaxStop就是您所追求的。这两个处理程序不必直接附加到your AJAX methods,它们可以在单元测试中完成。

这些是正常事件(full list here),因此您可以根据需要.bind() / .unbind(),例如,当完成上述单元测试时:

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

答案 1 :(得分:1)

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

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

我不确定仅仅为了支持单元测试而使代码变得更复杂是值得的,尽管你可以说为异步函数添加回调是通用的。

另一种方法是让测试使用原始超时。

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