javascript 如何使用Jasmine验证jQuery AJAX 事件?

0g0grzrc  于 2023-03-06  发布在  Java
关注(0)|答案(6)|浏览(123)

我正在尝试使用Jasmine为基本的jQuery AJAX 请求编写一些BDD规范。我目前正在独立模式下使用Jasmine(即通过SpecRunner.html)。我已经配置了SpecRunner来加载jquery和其他.js文件。您知道为什么以下内容不起作用吗?has_returned没有变为true,即使“yuppi!”警报显示正常。

describe("A jQuery ajax request should be able to fetch...", function() {

  it("an XML file from the filesystem", function() {
    $.ajax_get_xml_request = { has_returned : false };  
    // initiating the AJAX request
    $.ajax({ type: "GET", url: "addressbook_files/addressbookxml.xml", dataType: "xml",
             success: function(xml) { alert("yuppi!"); $.ajax_get_xml_request.has_returned = true; } }); 
    // waiting for has_returned to become true (timeout: 3s)
    waitsFor(function() { $.ajax_get_xml_request.has_returned; }, "the JQuery AJAX GET to return", 3000);
    // TODO: other tests might check size of XML file, whether it is valid XML
    expect($.ajax_get_xml_request.has_returned).toEqual(true);
  }); 

});

我如何测试回调是否被调用?任何指向与使用Jasmine测试异步jQuery相关的博客/材料的指针都将非常感谢。

8yoxcaq7

8yoxcaq71#

我想你可以做两种测试:
1.伪造 AJAX 请求的单元测试(使用Jasmine的spies),使你能够测试所有在AJAX请求之前和之后运行的代码。你甚至可以使用Jasmine伪造来自服务器的响应。这些测试会更快--而且它们不需要处理异步行为--因为没有任何真实的的AJAX在运行。
1.执行真实的 AJAX 请求的集成测试。这些需要是异步的。
茉莉可以帮你做这两种测试。
下面是一个示例,说明如何伪造 AJAX 请求,然后编写一个单元测试来验证伪造的AJAX请求是否指向正确的URL:

it("should make an AJAX request to the correct URL", function() {
    spyOn($, "ajax");
    getProduct(123);
    expect($.ajax.mostRecentCall.args[0]["url"]).toEqual("/products/123");
});

function getProduct(id) {
    $.ajax({
        type: "GET",
        url: "/products/" + id,
        contentType: "application/json; charset=utf-8",
        dataType: "json"
    });
}

对于Jasmine 2.0,请改用:

expect($.ajax.calls.mostRecent().args[0]["url"]).toEqual("/products/123");

如本答复所述
下面是一个类似的单元测试,用于验证在 AJAX 请求成功完成时是否执行了回调:

it("should execute the callback function on success", function () {
    spyOn($, "ajax").andCallFake(function(options) {
        options.success();
    });
    var callback = jasmine.createSpy();
    getProduct(123, callback);
    expect(callback).toHaveBeenCalled();
});

function getProduct(id, callback) {
    $.ajax({
        type: "GET",
        url: "/products/" + id,
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: callback
    });
}

对于Jasmine 2.0,请改用:

spyOn($, "ajax").and.callFake(function(options) {

如本答复所述
最后,您在其他地方暗示过,出于集成的目的,您可能希望编写发出真实的 AJAX 请求的集成测试。这可以使用Jasmine的异步特性来完成:等待()、等待()和运行():

it("should make a real AJAX request", function () {
    var callback = jasmine.createSpy();
    getProduct(123, callback);
    waitsFor(function() {
        return callback.callCount > 0;
    });
    runs(function() {
        expect(callback).toHaveBeenCalled();
    });
});

function getProduct(id, callback) {
    $.ajax({
        type: "GET",
        url: "data.json",
        contentType: "application/json; charset=utf-8"
        dataType: "json",
        success: callback
    });
}
xwmevbvl

xwmevbvl2#

看看jasmine-ajax项目:http://github.com/pivotal/jasmine-ajax.
它是一个插入式助手,(对于jQuery或Prototype.js)stub位于XHR层,这样请求就不会发出,然后您就可以对请求有所期待。
然后,它允许您为所有案例提供fixture响应,然后为您想要的每个响应编写测试:成功、失败、未授权等。
它使Ajax调用脱离了异步测试的范畴,并为测试实际响应处理程序的工作方式提供了很大的灵活性。

yyyllmsg

yyyllmsg3#

下面是一个简单的示例测试套件,用于类似下面的appjs

var app = {
               fire: function(url, sfn, efn) {
                   $.ajax({
                       url:url,
                       success:sfn,
                       error:efn
                   });
                }
         };

一个示例测试套件,它将基于url regexp调用callback

describe("ajax calls returns", function() {
 var successFn, errorFn;
 beforeEach(function () {
    successFn = jasmine.createSpy("successFn");
    errorFn = jasmine.createSpy("errorFn");
    jQuery.ajax = spyOn(jQuery, "ajax").andCallFake(
      function (options) {
          if(/.*success.*/.test(options.url)) {
              options.success();
          } else {
              options.error();
          }
      }
    );
 });

 it("success", function () {
     app.fire("success/url", successFn, errorFn);
     expect(successFn).toHaveBeenCalled();
 });

 it("error response", function () {
     app.fire("error/url", successFn, errorFn);
     expect(errorFn).toHaveBeenCalled();
 });
});
c6ubokkw

c6ubokkw4#

当我用Jasmine指定 AJAX 代码时,我通过监视任何依赖函数启动远程调用(比如,$.get或$ajax)来解决这个问题,然后我检索设置在它上面的回调并分别测试它们。
我最近举了一个例子:
https://gist.github.com/946704

cx6n0qe3

cx6n0qe35#

试试jqueryspy.com它提供了一个优雅的jquery语法来描述你的测试,并允许在 AJAX 完成后回调测试,它非常适合集成测试,你可以配置ajax的最大等待时间(秒或毫秒)。

sg24os4d

sg24os4d6#

我觉得我需要提供一个更新的答案,因为Jasmine现在是2.4版本,并且一些功能已经从2.0版本更改。
因此,要验证 AJAX 请求中是否调用了回调函数,您需要创建一个spy,添加一个callFake函数,然后将spy用作回调函数。

describe("when you make a jQuery AJAX request", function()
{
    it("should get the content of an XML file", function(done)
    {
        var success = jasmine.createSpy('success');
        var error = jasmine.createSpy('error');

        success.and.callFake(function(xml_content)
        {
            expect(success).toHaveBeenCalled();

            // you can even do more tests with xml_content which is
            // the data returned by the success function of your AJAX call

            done(); // we're done, Jasmine can run the specs now
        });

        error.and.callFake(function()
        {
            // this will fail since success has not been called
            expect(success).toHaveBeenCalled();

            // If you are happy about the fact that error has been called,
            // don't make it fail by using expect(error).toHaveBeenCalled();

            done(); // we're done
        });

        jQuery.ajax({
            type : "GET",
            url : "addressbook_files/addressbookxml.xml",
            dataType : "xml",
            success : success,
            error : error
        });
    });
});

我已经为success函数和error函数做了一些技巧,以确保即使 AJAX 返回错误,Jasmine也会尽快运行规范。
如果你没有指定一个错误函数,而你 AJAX 返回了一个错误,你将不得不等待5秒(默认的超时间隔),直到Jasmine抛出一个错误Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.

it("should get the content of an XML file", function(done)
{
    // your code
},
10000); // 10 seconds

相关问题