如何伪造jquery.ajax()响应?

时间:2022-08-25 16:26:09

I am writing some QUnit tests for a JavaScript that makes AJAX calls.

我正在为进行AJAX调用的JavaScript编写一些QUnit测试。

For isolation I overwrite $.ajax to write the parameter array of an AJAX call to a variable. This works to test how methods use AJAX functions, but I have difficulty testing the success handler of $.load()

对于隔离,我覆盖$。将ajax调用的参数数组写入变量。这可以测试方法如何使用AJAX函数,但是我很难测试$.load()的成功处理程序

From the documentation at http://api.jquery.com/load/:

来自http://api.jquery.com/load/的文档:

When a successful response is detected (i.e. when textStatus is "success" or "notmodified"), .load() sets the HTML contents of the matched element to the returned data.

当检测到一个成功的响应(例如,当textStatus为“success”或“notmodified”)时,.load()将匹配元素的HTML内容设置为返回的数据。

So I have attempted to return an object containing objects with the same name as variables for the success handler:

因此,我尝试返回一个对象,该对象包含与成功处理程序的变量同名的对象:

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

But this approach hasn't worked.

但这种方法并没有奏效。

How can I replicate the behaviour of a successful AJAX call?

如何复制成功的AJAX调用的行为?

6 个解决方案

#1


16  

This question has a few years and for the new versions of jQuery has changed a bit.

这个问题已经有几年的历史了,新版本的jQuery也有了一些变化。

To do this with Jasmin you can try Michael Falaga's approach

你可以试试迈克尔·法拉加的方法

Solution

解决方案

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

With Jasmine

用茉莉花

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

No Jasmine

没有茉莉花

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

#2


14  

After reading inspired by @Robusto and @Val, I found a method that works:

在阅读了@Robusto和@Val的启发后,我发现了一个行之有效的方法:

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

Instead of raising the event from any real $.ajax code or by triggering any events, I have my fake ajax object call the function (which is passed in as a parameter to $.ajax()) as part of my fake function.

而不是从任何实际的资金中筹集。ajax代码或通过触发任何事件,我让伪ajax对象调用函数(作为参数传入$.ajax())作为伪函数的一部分。

#3


9  

Use a closure to override $.ajax with a dummy response

After trying the accepted answer and the answer posted by user1634074, I devised this simple and flexible blend of the two.

在尝试了user1634074发布的公认答案和答案之后,我设计了这两个简单而灵活的混合。

In its most basic form…

以最基本的形式……

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

In the above example, define a function ajax_response() that accepts some JSON string as an argument (or any number of custom arguments useful for simulating a response) and returns an anonymous closure function that will be assigned to $.ajax as an override for unit testing.

在上面的示例中,定义一个函数ajax_response(),该函数接受一些JSON字符串作为参数(或任何数量的用于模拟响应的自定义参数),并返回一个将分配给$的匿名闭包函数。ajax作为单元测试的重写。

The anonymous function accepts a params argument which will contain the settings object passed to the $.ajax function. And it uses the argument(s) passed to the outer function to simulate a response from the server. In this example, it always simulates a successful response from the server, by simply invoking the success callback and supplying it with the dummy JSON.

匿名函数接受params参数,该参数将包含传递给$的settings对象。ajax功能。它使用传递给外部函数的参数来模拟服务器的响应。在本例中,它总是通过简单地调用success回调并提供假JSON来模拟服务器的成功响应。

It is easy to reconfigure…

很容易重新配置…

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

Below we can see it in action…

下面我们可以看到它的行动……

/* 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>

#4


2  

Mock $.ajax as needed without disturbing jQuery

The answers here are good but had a specific need to build out a fake response to a single API call while leaving all other API calls the same until the backend service was built out so I can continue building stuff on the UI.

这里的答案很好,但是有一个特定的需求,即构建一个对单个API调用的虚假响应,同时保留所有其他API调用,直到构建后端服务,以便我可以继续在UI上构建东西。

The API object uses $.ajax under the hood so you can call an API method like so:

API对象使用$。下面是ajax,你可以这样调用API方法:

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

This method does the trick:

这种方法很管用:

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

Then override a single api call without touching $.ajax:

然后在不触及$.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/

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

#5


1  

Look at the jQuery documentation: You'll see that the Ajax setup provides a number of other conditions that are tested for. If you make them all point to your fakeAjaxSuccess, you might achieve for your objective.

查看jQuery文档:您将看到Ajax设置提供了许多其他测试条件。如果您让他们都指向您的fakeAjaxSuccess,那么您可能实现您的目标。

Alternatively, wrap your $.ajax call into its own function and have whatever calls it simply call your event handler with the fakeAjaxSuccess object.

另外,包装你的美元。ajax调用自己的函数,并使用fakeAjaxSuccess对象调用事件处理程序。

#6


1  

I think the link below should help. as for a parameter I am not so sure but it could be .

我认为下面的链接应该会有所帮助。至于参数,我不太确定,但可能是。

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

Override jQuery .val() function?

覆盖jQuery .val()函数?

#1


16  

This question has a few years and for the new versions of jQuery has changed a bit.

这个问题已经有几年的历史了,新版本的jQuery也有了一些变化。

To do this with Jasmin you can try Michael Falaga's approach

你可以试试迈克尔·法拉加的方法

Solution

解决方案

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

With Jasmine

用茉莉花

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

No Jasmine

没有茉莉花

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

#2


14  

After reading inspired by @Robusto and @Val, I found a method that works:

在阅读了@Robusto和@Val的启发后,我发现了一个行之有效的方法:

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

Instead of raising the event from any real $.ajax code or by triggering any events, I have my fake ajax object call the function (which is passed in as a parameter to $.ajax()) as part of my fake function.

而不是从任何实际的资金中筹集。ajax代码或通过触发任何事件,我让伪ajax对象调用函数(作为参数传入$.ajax())作为伪函数的一部分。

#3


9  

Use a closure to override $.ajax with a dummy response

After trying the accepted answer and the answer posted by user1634074, I devised this simple and flexible blend of the two.

在尝试了user1634074发布的公认答案和答案之后,我设计了这两个简单而灵活的混合。

In its most basic form…

以最基本的形式……

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

In the above example, define a function ajax_response() that accepts some JSON string as an argument (or any number of custom arguments useful for simulating a response) and returns an anonymous closure function that will be assigned to $.ajax as an override for unit testing.

在上面的示例中,定义一个函数ajax_response(),该函数接受一些JSON字符串作为参数(或任何数量的用于模拟响应的自定义参数),并返回一个将分配给$的匿名闭包函数。ajax作为单元测试的重写。

The anonymous function accepts a params argument which will contain the settings object passed to the $.ajax function. And it uses the argument(s) passed to the outer function to simulate a response from the server. In this example, it always simulates a successful response from the server, by simply invoking the success callback and supplying it with the dummy JSON.

匿名函数接受params参数,该参数将包含传递给$的settings对象。ajax功能。它使用传递给外部函数的参数来模拟服务器的响应。在本例中,它总是通过简单地调用success回调并提供假JSON来模拟服务器的成功响应。

It is easy to reconfigure…

很容易重新配置…

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

Below we can see it in action…

下面我们可以看到它的行动……

/* 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>

#4


2  

Mock $.ajax as needed without disturbing jQuery

The answers here are good but had a specific need to build out a fake response to a single API call while leaving all other API calls the same until the backend service was built out so I can continue building stuff on the UI.

这里的答案很好,但是有一个特定的需求,即构建一个对单个API调用的虚假响应,同时保留所有其他API调用,直到构建后端服务,以便我可以继续在UI上构建东西。

The API object uses $.ajax under the hood so you can call an API method like so:

API对象使用$。下面是ajax,你可以这样调用API方法:

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

This method does the trick:

这种方法很管用:

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

Then override a single api call without touching $.ajax:

然后在不触及$.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/

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

#5


1  

Look at the jQuery documentation: You'll see that the Ajax setup provides a number of other conditions that are tested for. If you make them all point to your fakeAjaxSuccess, you might achieve for your objective.

查看jQuery文档:您将看到Ajax设置提供了许多其他测试条件。如果您让他们都指向您的fakeAjaxSuccess,那么您可能实现您的目标。

Alternatively, wrap your $.ajax call into its own function and have whatever calls it simply call your event handler with the fakeAjaxSuccess object.

另外,包装你的美元。ajax调用自己的函数,并使用fakeAjaxSuccess对象调用事件处理程序。

#6


1  

I think the link below should help. as for a parameter I am not so sure but it could be .

我认为下面的链接应该会有所帮助。至于参数,我不太确定,但可能是。

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

Override jQuery .val() function?

覆盖jQuery .val()函数?