How to fake jquery.ajax() response?
I am writing some QUnit tests for a JavaScript that makes AJAX calls.
For isolation I overwrite $.ajax
to write the parameter array of an AJAX call to a variable. This works to开发者_JS百科 test how methods use AJAX functions, but I have difficulty testing the success handler of $.load()
From the documentation at 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.
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?
This question has a few years and for the new versions of jQuery has changed a bit.
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]
});
After reading inspired by @Robusto and @Val, I found a method that works:
//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.
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.
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.
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.
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>
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.
The API object uses $.ajax under the hood so you can call an API method like so:
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:
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/
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.
Alternatively, wrap your $.ajax
call into its own function and have whatever calls it simply call your event handler with the fakeAjaxSuccess
object.
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?
Here is a simple working solution
var set_ajax_response = function(data){
$.ajax = $.Deferred().resolve(data).promise;
}
var data = [1,2,3];
set_ajax_response(data);
精彩评论