私はJasmineを使用して、基本的なjQuery AJAX要求のBDD仕様を記述しようとしています。現在、Jasmineをスタンドアロンモードで使用しています(つまり、SpecRunner.html
)。 jqueryおよびその他の.jsファイルをロードするようにSpecRunnerを構成しました。以下が機能しない理由はありますか? 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のテストに関連するブログ/資料へのポインタは大歓迎です。
次の2種類のテストを実行できます。
ジャスミンは、両方の種類のテストの実行を支援できます。
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の非同期機能を使用して実行できます: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 。
これは、(jQueryまたはPrototype.jsのいずれかで)XHRレイヤーでスタブ化して、リクエストが送信されないようにするドロップインヘルパーです。その後、リクエストについて必要なすべてを期待できます。
次に、すべてのケースにフィクスチャの応答を提供し、必要な応答ごとにテストを記述できます。成功、失敗、不正など。
非同期テストの領域からAjax呼び出しを取得し、実際の応答ハンドラーの動作をテストするための柔軟性を大幅に提供します。
これは、このようなアプリjsの簡単なテストスイートの例です
var app = {
fire: function(url, sfn, efn) {
$.ajax({
url:url,
success:sfn,
error:efn
});
}
};
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();
});
});
Jasmineでajaxコードを指定するとき、リモート呼び出しを開始する依存関数($ .getや$ ajaxなど)をスパイすることで問題を解決します。次に、設定されたコールバックを取得し、個別にテストします。
最近私が要点を示した例は次のとおりです。
Jqueryspy.comを試すテストを記述する構文のようなエレガントなjqueryを提供し、ajaxの完了後にコールバックがテストできるようにします。統合テストに最適で、最大のAjax待機時間を秒またはミリ秒単位で構成できます。
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=がエラーを返した場合でもJasmineができるだけ早く仕様を実行するようにするために、成功関数とエラー関数のトリックを行いました。
エラー関数を指定せずにAJAXがエラーを返す場合、Jasmineがエラーをスローするまで5秒(デフォルトのタイムアウト間隔)待つ必要があります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