2011-01-11 12 views
107

jasmineを使用して、基本的なjQuery AJAXリクエストのBDD仕様を記述しようとしています。私は現在スタンドアロンモードでジャスミンを使用しています(つまりSpecRunner.htmlまで)。 jqueryやその他の.jsファイルを読み込むようにSpecRunnerを設定しました。次の理由がうまくいかない理由はありますか? has_returnedは "yuppi!"と思っても真実にならないアラートが正常に表示されます。JasmineでjQuery AJAXイベントを確認するにはどうすればよいですか?

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をテストすることに関連するブログ/マテリアルへのあらゆる指針は、非常に高く評価されます。

答えて

12

jasmine-ajaxプロジェクト:http://github.com/pivotal/jasmine-ajaxを見てください。

これは、(jQueryまたはPrototype.jsの)スタブをXHRレイヤーに配置して、要求が外に出ないようにするためのドロップインヘルパーです。あなたはその要求についてあなたが望むすべてを期待することができます。

その後、それはあなたがすべてのあなたのケースのためのフィクスチャの応答を提供し、その後、あなたがしたいことを各応答のためのテストを書くことができます:成功、失敗、不正など

それはAjaxは、非同期テストの領域の外に呼び出してとり、実際のレスポンスハンドラの動作方法をテストするための柔軟性を提供します。

+0

ありがとう@jasminebdd、jasmine-ajaxプロジェクトは、私のjsコードのテストに行く方法のように見えます。しかし、サーバーへの実際のリクエストでテストしたい場合はどうでしょうか?接続性/統合性テストのために? – mnacos

+2

@mnacos jasmine-ajaxは、単体テストに役立ちます。この場合、特にサーバーへの呼び出しを避けたいとします。統合テストを行っている場合、これはおそらくあなたが望むものではなく、別のテスト戦略として設計する必要があります。 –

4

私はジャスミンでajaxコードを指定すると、リモート呼び出し(例えば$ .getや$ ajaxのような)を起動する依存する関数を偵察することで問題を解決します。それから私はそれに設定されたコールバックを取得し、それらを離散的にテストします。私はあなたが行うことができますテストの2種類があると思います

https://gist.github.com/946704

227

:ここ

は、私が最近gisted例です

  1. ユニットテストは、その偽のAJAX要求(ジャスミンのスパイを使用して) の直前にのAJAXリクエストを実行し、の直後にのコードをテストすることができます。 Jasmineを使用して、サーバーからの応答を偽装することさえできます。これらのテストはより速く、非同期動作を処理する必要はありません。実際のAJAXは実行されていないためです。
  2. 実際のAJAX要求を実行する統合テスト。これらは非同期である必要があります。

ジャスミンは、両方の種類のテストを行うのに役立ちます。

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:ここでは

を使用すると、偽のAJAX要求し、その後偽造AJAXリクエストが正しいURLに行っていたことを確認するために、ユニットテストを書くことができるかのサンプルです。代わりに0使用:ジャスミン については

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

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

ここ

this answerに述べたように、あなたのコールバックを確認する同様のユニットテストは、AJAXリクエストが正常に完了すると、実行されたです2.0代わりに:

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

this answer

最後に、統合のために実際のAJAXリクエストを行う統合テストを作成することをお勧めします。これは、ジャスミンのasyncronous機能を使用して行うことができます。待機()、waitsFor()と実行():

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

+1アレックス素晴らしい答え。実際に私は[Deferredオブジェクトを使ったテストAjaxリクエスト](http://stackoverflow.com/questions/12080087/test-ajax-request-using-the-deferred-object)という質問を開いた同様の問題に直面しました。あなたは見てみることができますか?ありがとう。 –

+12

あなたの答えはJasmineの公式文書の一部であることを本当に願っています。数日間私を殺していた問題に対する非常に明確な答え。 –

+0

優れた答えと例。ありがとうございました。 –

0

は、それはあなたのテストを記述するための構文のようなエレガントなjqueryのを提供し、コールバックが後にテストすることができますjqueryspy.com をお試しくださいアヤックスは完成しました。統合テストに最適で、最大のAjax待機時間を秒単位またはミリ秒単位で構成できます。ここ

5

は私が必要とするように私が感じるこの

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

URLの正規表現

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(); 
}); 
}); 
+0

ありがとう。この例は私を大いに助けました! Jasmine> 2.0を使用している場合、andCallFakeの構文は spyOn(jQuery、 "ajax")and.callFake(/ * your function * /)です。 –

0

に基づいてコールバックを呼び出しますサンプルテストスイートのようなアプリのJSのための簡単な例のテストスイート ですJasmineがバージョン2.4になり、いくつかの機能がバージョン2.0から変更されて以来、より最新の回答を提供することができます。

したがって、AJAXリクエスト内でコールバック関数が呼び出されたことを確認するには、スパイを作成し、callFake関数を追加してからコールバック関数として使用する必要があります。

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

私はジャスミンはできるだけ早くあなたのAJAXがエラーを返した場合でも、スペックを実行することを確認するために、成功の機能のためのトリックだけでなく、誤差関数をやった:ここでは、それがどのようになるのです。

エラー関数を指定せずにAJAXがエラーを返す場合は、JasmineがエラーTimeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.をスローするまで5秒間(デフォルトのタイムアウト間隔)待たなければなりません。

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