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

mna*_*cos 113 javascript ajax bdd jquery jasmine

我正在尝试使用Jasmine为基本的jQuery AJAX请求编写一些BDD规范.我目前在独立模式下使用Jasmine(即通过SpecRunner.html).我已配置SpecRunner来加载jquery和其他.js文件.任何想法为什么以下不起作用?has_returned并不成真,甚至想到了"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);
  }); 

});
Run Code Online (Sandbox Code Playgroud)

如何测试是否已调用回调?任何与使用Jasmine测试async jQuery相关的博客/材料的指针将不胜感激.

Ale*_*ork 232

我想你可以做两种类型的测试:

  1. 单元测试是假的AJAX请求(使用茉莉花的间谍),使您能够测试所有的代码运行的之前的AJAX请求,而只是事后.您甚至可以使用Jasmine伪造来自服务器的响应.这些测试会更快 - 而且他们不需要处理异步行为 - 因为没有任何真正的AJAX正在进行.
  2. 执行真正的AJAX请求的集成测试.这些都需要是异步的.

Jasmine可以帮助您进行两种测试.

以下是如何伪造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"
    });
}
Run Code Online (Sandbox Code Playgroud)

对于Jasmine 2.0使用:

expect($.ajax.calls.mostRecent().args[0]["url"]).toEqual("/products/123");
Run Code Online (Sandbox Code Playgroud)

正如这个答案所述

这是一个类似的单元测试,在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
    });
}
Run Code Online (Sandbox Code Playgroud)

对于Jasmine 2.0使用:

spyOn($, "ajax").and.callFake(function(options) {
Run Code Online (Sandbox Code Playgroud)

正如这个答案所述

最后,您已在其他地方暗示您可能希望编写实现AJAX请求的集成测试 - 用于集成目的.这可以使用Jasmine的异步功能来完成:waits(),waitsFor()和runs():

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
    });
}
Run Code Online (Sandbox Code Playgroud)

  • 我真的希望你的回答是Jasmine官方文档的一部分.几天来一直杀了我的问题非常清楚. (12认同)
  • 这个答案应该真正标记为这个问题的正式答案. (4认同)

小智 13

看看jasmine-ajax项目:http://github.com/pivotal/jasmine-ajax.

它是XHR层(对于jQuery或Prototype.js)存根的一个直接帮助,因此请求永远不会消失.然后,您可以期望所有您想要的请求.

然后,它允许您为所有案例提供夹具响应,然后为您想要的每个响应编写测试:成功,失败,未授权等.

它将Ajax调用排除在异步测试领域之外,并为测试实际响应处理程序应如何工作提供了很大的灵活性.

  • @mnacos jasmine-ajax主要用于单元测试,在这种情况下,您特别希望避免调用服务器.如果您正在进行集成测试,这可能不是您想要的,应该设计为单独的测试策略. (2认同)

ski*_*ipy 7

这是一个简单的示例测试套件,适用于这样的app js

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

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

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();
 });
});
Run Code Online (Sandbox Code Playgroud)


Jus*_*rls 5

当我用Jasmine指定ajax代码时,我通过监视任何依赖的函数启动远程调用来解决问题(例如,$ .get或$ ajax).然后我检索在其上设置的回调并离散地测试它们.

这是我最近提出的一个例子:

https://gist.github.com/946704