如何用JasminevalidationjQuery AJAX事件?

我正在尝试使用Jasmine为基本的jQuery AJAX请求编写一些BDD规范。 我目前在独立模式(即通过SpecRunner.html )使用茉莉花。 我configuration了SpecRunner来加载jQuery和其他.js文件。 任何想法为什么以下不起作用? 回复不成真,甚至认为“雅皮”! 警报显示正常。

 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); }); }); 

我如何testingcallback已被调用? 任何指向与JasminetestingasynchronousjQuery有关的博客/材料将不胜感激。

我猜测你可以做两种types的testing:

  1. unit testing,假的AJAX请求(使用茉莉的间谍),使您能够testing所有的代码运行 AJAX请求之前 ,以及之后 。 你甚至可以用Jasmine来伪造服务器的响应。 这些testing会更快 – 并且不需要处理asynchronous行为 – 因为没有任何真正的AJAX正在进行。
  2. 集成testing,执行真正的AJAX请求。 这些将需要asynchronous。

茉莉花可以帮助你做两种testing。

下面是如何伪造AJAX请求的示例,然后编写unit testing以validation伪造的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" }); } 

对于茉莉花2.0使用,而不是:

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

正如在这个答案中指出的

下面是一个类似的unit testing,validation您的callback是在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 }); } 

对于茉莉花2.0使用,而不是:

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

正如在这个答案中指出的

最后,你已经暗示其他地方,你可能想编写集成testing,真正的AJAX请求 – 为了集成的目的。 这可以通过使用Jasmine的asynchronous特性来完成: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 }); } 

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

它是一个embedded式帮助程序(对于jQuery或Prototype.js)存根在XHR层,以便请求永远不会出去。 然后,您可以期待所有你想要的请求。

然后它可以让你为所有情况提供夹具反应,然后为每个你想要的反应写成testing:成功,失败,未经授权等。

它将Ajax调用放在asynchronoustesting的范围之外,并为您提供了很大的灵活性来testing您的实际响应处理程序的工作方式。

这里是一个简单的示例testing套件,适用于这样的应用程序

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

一个样本testing套件,它将根据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(); }); }); 

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

最近我举了一个例子:

https://gist.github.com/946704

试试jqueryspy.com它提供了一个优雅的jquery类似的语法来描述你的testing,并允许callbacktesting后,Ajax完成。 它非常适合集成testing,你可以在几秒或者几秒内configuration最大的ajax等待时间。

我觉得我需要提供一个更新的答案,因为茉莉花现在在2.4版本,一些function已经从2.0版本改变。

所以,为了validation在你的AJAX请求中调用了一个callback函数,你需要创build一个spy,添加一个callFake函数,然后使用spy作为你的callback函数。 这是怎么回事:

 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 }); }); }); 

我已经完成了成功函数和错误函数的窍门,以确保Jasmine将尽快运行规格,即使您的AJAX返回错误。

如果你没有指定一个错误函数,并且你的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