web-dev-qa-db-ja.com

jquery.ajax()レスポンスを偽造する方法は?

AJAX呼び出しを行うJavaScriptのQUnitテストをいくつか書いています。

分離のために、_$.ajax_を上書きして、変数へのAJAX呼び出しのパラメーター配列を書き込みます。これは、メソッドがAJAX関数を使用する方法をテストするために、しかし、私は $.load() の成功ハンドラをテストするのが難しい

http://api.jquery.com/load/ のドキュメントから:

成功した応答が検出された場合(つまり、textStatusが「success」または「notmodified」の場合)、. load()は一致した要素のHTMLコンテンツを返されたデータに設定します。

そのため、成功ハンドラーの変数と同じ名前のオブジェクトを含むオブジェクトを返そうとしました。

_    //Mock ajax function
    $.ajax = function (param) {
        _mockAjaxOptions = param;
        var fakeAjaxSuccess = { responseText: "success", textStatus: "success", XMLHttpRequest: "success" };
        return fakeAjaxSuccess;
    };
_

しかし、このアプローチはうまくいきませんでした。

成功したAJAX呼び出しの動作を再現するにはどうすればよいですか?

37
StuperUser

@Robustoと@Valに触発された読書の後、私は動作する方法を見つけました:

_//Mock ajax function
$.ajax = function (param) {
    _mockAjaxOptions = param;
    //call success handler
    param.complete("data", "textStatus", "jqXHR");
};
_

実際の$ .ajaxコードからイベントを発生させたり、イベントをトリガーしたりする代わりに、偽のajaxオブジェクトに、関数($.ajax()へのパラメーターとして渡される)を偽の関数の一部として呼び出させます。

14
StuperUser

この質問には数年かかり、jQueryの新しいバージョンでは少し変更されています。

ジャスミンでこれを行うには、 マイケルファラガのアプローチ を試すことができます

ソリューション

  function ajax_response(response) {
    var deferred = $.Deferred().resolve(response);
    return deferred.promise();
  }

ジャスミン使用

  describe("Test test", function() {
    beforeEach(function() {
      spyOn($, 'ajax').and.returnValue(
        ajax_response([1, 2, 3])
      );
    });
    it("is it [1, 2, 3]", function() {
      var response;
      $.ajax('GET', 'some/url/i/fancy').done(function(data) {
        response = data;
      });
      expect(response).toEqual([1, 2, 3]);
    });
  });

ジャスミンなし

  $.ajax = ajax_response([1, 2, 3]);
  $.ajax('GET', 'some/url/i/fancy').done(function(data) {
     console.log(data); // [1, 2, 3]
  });
24
user1634074

クロージャーを使用して、ダミーの応答で$.ajaxをオーバーライドします

受け入れられた答えser1634074によって投稿された答え を試した後、この2つの単純で柔軟なブレンドを考案しました。

最も基本的な形で…

function ajax_response(response) {
  return function (params) {
    params.success(response);
  };
}
$.ajax = ajax_response('{ "title": "My dummy JSON" }');

上記の例では、引数としてJSON文字列(または応答のシミュレーションに役立つ任意の数のカスタム引数)を受け取り、$.ajaxに割り当てられる匿名のクロージャー関数を返す関数ajax_response()を定義します単体テストのオーバーライド。

無名関数は、$.ajax関数に渡される設定オブジェクトを含むparams引数を受け入れます。そして、外部関数に渡された引数を使用して、サーバーからの応答をシミュレートします。この例では、successコールバックを呼び出してダミーのJSONを提供するだけで、サーバーからの正常な応答を常にシミュレートします。

簡単に再構成できます…

function ajax_response(response, success) {
  return function (params) {
    if (success) {
      params.success(response);
    } else {
      params.error(response);
    }
  };
}

// Simulate success
$.ajax = ajax_response('{ "title": "My dummy JSON." }', true); 
doAsyncThing(); // Function that calls $.ajax

// Simulate error
$.ajax = ajax_response('{ "error": "Who is the dummy now?" }', false); 
doAsyncThing(); // Function that calls $.ajax

以下で実際にそれを見ることができます…

/* FUNCTION THAT MAKES AJAX REQUEST */
function doAsyncThing() {
  $.ajax({
    type: "POST",
    url: "somefile.php",
    // data: {…},
    success: function (results) {
      var json = $.parseJSON(results),
          html = $('#ids').html();
      $('#ids').html(html + '<br />' + json.id);
    }
  });
}

/* BEGIN MOCK TEST */
// CREATE CLOSURE TO RETURN DUMMY FUNCTION AND FAKE RESPONSE
function ajax_response(response) {
  return function (params) {
    params.success(response);
  };
}

var n = Prompt("Number of AJAX calls to make", 10);

for (var i = 1; i <= n; ++i) {
  
  // OVERRIDE $.ajax WITH DUMMY FUNCTION AND FAKE RESPONSE
  $.ajax = ajax_response('{ "id": ' + i + ' }');
  doAsyncThing();
}
/* END MOCK TEST */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="ids">IDs:</p>
11
gfullam

JQueryを乱すことなく、必要に応じて$ .ajaxをモックする

ここでの答えは良いものですが、バックエンドサービスが構築されるまで他のすべてのAPI呼び出しを同じままにして、UIで何かを構築し続けることができるように、単一のAPI呼び出しに対する偽の応答を構築する必要がありました。

APIオブジェクトは内部で$ .ajaxを使用するため、次のようなAPIメソッドを呼び出すことができます。

api.products({ price: { $lt: 150, tags: ['nike', 'shoes'] } })
.done(function(json) {
  // do something with the data
})
.error(function(err) {
  // handle error
});

このメソッドはトリックを行います:

function mockAjax(options) {
  var that = {
    done: function done(callback) {
      if (options.success)
        setTimeout(callback, options.timeout, options.response);
      return that;
    },
    error: function error(callback) {
      if (!options.success)
        setTimeout(callback, options.timeout, options.response);
      return that;
    }
  };
  return that;
}

次に、$。ajaxに触れずに単一のAPI呼び出しをオーバーライドします。

api.products = function() {
  return mockAjax({
    success: true,
    timeout: 500,
    response: {
      results: [
        { upc: '123123', name: 'Jordans' },
        { upc: '4345345', name: 'Wind Walkers' }
      ]
    }
  });
};

https://jsfiddle.net/Lsf3ezaz/2/

4
Jason Sebring

下のリンクが役立つと思います。パラメータに関しては、私はそれほど確信していませんが、そうかもしれません。

$.fn.ajax.success =  function (){
  ///the rest goest here
}

jQuery .val()関数をオーバーライドしますか?

1
Val

JQueryのドキュメントを見てください:Ajaxセットアップは、テストされる他の多くの条件を提供することがわかります。それらをすべてあなたのfakeAjaxSuccessに向けると、目的を達成できる可能性があります。

または、$.ajax独自の関数を呼び出し、fakeAjaxSuccessオブジェクトを使用してイベントハンドラーを呼び出すだけです。

1
Robusto