Javascript 如何伪造 jquery.ajax() 响应?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5272698/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to fake jquery.ajax() response?
提问by StuperUser
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 调用的参数数组写入变量。这适用于测试方法如何使用 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 调用的行为?
采纳答案by StuperUser
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()
)作为我的假函数的一部分。
回答by user1634074
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
要使用 Jasmin 做到这一点,您可以尝试Michael Falaga 的方法
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]
});
回答by gfullam
Use a closure to override $.ajax
with a dummy response
使用闭包覆盖$.ajax
虚拟响应
After trying the accepted answerand 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
参数,该参数将包含传递给$.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>
回答by Jason Sebring
Mock $.ajax as needed without disturbing jQuery
在不干扰 jQuery 的情况下根据需要模拟 $.ajax
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' }
]
}
});
};
回答by Robusto
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
对象调用您的事件处理程序。
回答by Val
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
}