【问题标题】:Any better way than setTimeout to wait for asnyc callbacks when testing JavaScript?在测试 JavaScript 时,有什么比 setTimeout 更好的方法来等待异步回调?
【发布时间】:2013-07-21 04:57:42
【问题描述】:

鉴于此代码:

showForm = function (url) {
        return $.get(url, function (html) {
             $('body').append();              
        });
 };

当使用sinon.jsjQuery.mockjax.jsexpect.js时,我有以下通过测试:

it("showForm calls jQuery.append", function () {

    $.mockjax({
          url: '/fake'                    
    });

    var spy = sinon.spy($.fn, "append");             
    presenter.showForm('/fake');

    setTimeout(function () { 
        expect(spy.called).to.be.equal(true);
    }, 1000);
});

使用 setTimeout 函数等待来自异步 $.get 的回调很难闻,如果我做太多,它会减慢我的测试套件。

但是,我觉得意图相当明确,并且似乎确实测试了我想要的。

有没有更好的方法,你能解释一下你的答案是怎么回事吗?

【问题讨论】:

  • 你能让ajax调用异步:false吗?
  • 谢谢,在这种情况下,不在 mockjax 服务器中(我可以看到)

标签: javascript jquery sinon


【解决方案1】:

传递您的匿名函数以将表单显示为参数,并在追加后在回调中调用它。为确保它被调用,您可以将其设为一个涵盖错误回调的 $.ajax 请求。

这种方式在 get 请求结束时准确调用它,没有多余的时间或调用太早。

showForm = function (url, callback) {
        return $.get(url, function (html) {
             $('body').append();   
             if(callback != undefined)
             callback();
        });
 };

it("showForm calls jQuery.append", function () {

    $.mockjax({
          url: '/fake'                    
    });

    var spy = sinon.spy($.fn, "append");

    presenter.showForm('/fake', function (){ 
        expect(spy.called).to.be.equal(true);
    });
});

【讨论】:

  • 谢谢 - 我喜欢这样 - 我唯一不确定的是添加回调只是为了测试目的。这被认为是好的做法吗?
  • 更好的是,通过测试if(callback){callback()} 使回调成为可选。这样您就不需要修改生产代码,但允许测试代码根据需要通过回调
  • @davy:为了使代码可测试,是的,现在通常认为这是一种好的做法。拥有经过测试的代码比无法测试的代码更好,即使使代码可测试实际上可能会降低可读性。
  • @davy,它可能。在您的代码中添加注释以提醒您之后将其删除,我添加了 slebetman 的建议,以便它与其他调用一起使用。
【解决方案2】:

你应该使用 sinons fakeServer。这将在调用 $.ajax 时立即调用您的 ajax 回调。看到这个jsFiddle

before(function(){
  var server = sinon.fakeServer.create();
  server.respondWith('response');
})

it("showForm calls jQuery.append", function () {
    var spy = sinon.spy($.fn, "append");             
    presenter.showForm('/fake');
    server.respond();
    expect(spy.called).to.be.equal(true);
});

【讨论】:

  • 谢谢,抱歉,Andreas,这返回 false - 我需要调查 fakeServer 的链接,除非你能发现明显的东西?
  • 嗯,由于某些原因,autoRespond=true 在这里不起作用,更新了我的答案
【解决方案3】:

使用 $.doTimeout 插件

查看以下文档。

http://benalman.com/projects/jquery-dotimeout-plugin/

希望对你有帮助

【讨论】:

    猜你喜欢
    • 2022-11-04
    • 2019-11-15
    • 2012-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-21
    • 2021-06-30
    • 1970-01-01
    相关资源
    最近更新 更多