Как подделать ответ jquery.ajax()?
Я пишу несколько тестов QUnit для JavaScript, который вызывает вызовы AJAX.
Для изоляции я перезаписываю $.ajax
, чтобы написать массив параметров вызова AJAX для переменной. Это работает, чтобы проверить, как методы используют функции AJAX, но мне трудно проверить обработчик успеха $.load()
Из документации в http://api.jquery.com/load/:
Когда обнаружен успешный ответ (т.е. когда textStatus является "успешным" или "немодифицированным" ),.load() устанавливает содержимое HTML сопоставленного элемента в возвращаемые данные.
Итак, я попытался вернуть объект, содержащий объекты с тем же именем, что и переменные для обработчика успеха:
//Mock ajax function
$.ajax = function (param) {
_mockAjaxOptions = param;
var fakeAjaxSuccess = { responseText: "success", textStatus: "success", XMLHttpRequest: "success" };
return fakeAjaxSuccess;
};
Но этот подход не сработал.
Как я могу воспроизвести поведение успешного вызова AJAX?
Ответы
Ответ 1
После чтения, вдохновленного @Robusto и @Val, я нашел метод, который работает:
//Mock ajax function
$.ajax = function (param) {
_mockAjaxOptions = param;
//call success handler
param.complete("data", "textStatus", "jqXHR");
};
Вместо того, чтобы поднимать событие из любого реального кода $.ajax или запускать любые события, у меня есть мой поддельный объект ajax, вызывающий функцию (которая передается как параметр в $.ajax()
) как часть моей поддельной функции.
Ответ 2
У этого вопроса есть несколько лет, и для новых версий jQuery немного изменилось.
Чтобы сделать это с помощью Jasmin, вы можете попробовать подход Майкла Фалаги
Решение
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]
});
Ответ 3
Используйте замыкание для переопределения $.ajax
с фиктивным ответом
После попытки принятого ответа и ответа, опубликованного пользователем1634074, я разработал эту простую и гибкую смесь из двух.
В своей самой простой форме...
function ajax_response(response) {
return function (params) {
params.success(response);
};
}
$.ajax = ajax_response('{ "title": "My dummy JSON" }');
В приведенном выше примере определите функцию ajax_response()
, которая принимает некоторую строку JSON в качестве аргумента (или любое количество настраиваемых аргументов, полезных для имитации ответа) и возвращает функцию анонимного закрытия, которая будет назначена $.ajax
as переопределение для модульного тестирования.
Анонимная функция принимает аргумент params
, который будет содержать объект настроек, переданный функции $.ajax
. И он использует аргумент (ы), переданный внешней функции, для имитации ответа с сервера. В этом примере он всегда имитирует успешный ответ от сервера, просто вызывая обратный вызов 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>
Ответ 4
Mock $.ajax при необходимости без нарушения jQuery
Ответы здесь хороши, но им нужна конкретная потребность в создании поддельного ответа на один вызов API, оставив все остальные вызовы 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;
}
Затем переопределите один вызов api, не касаясь $.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/
Ответ 5
Посмотрите на документацию jQuery: вы увидите, что установка Ajax предоставляет ряд других условий, на которые протестированы. Если вы сделаете все, что указывает на ваш fakeAjaxSuccess, вы можете достичь своей цели.
В качестве альтернативы, оберните свой вызов $.ajax
в свою собственную функцию и вызовите все вызовы, которые он просто вызывает обработчик событий с объектом fakeAjaxSuccess
.
Ответ 6
Я думаю, что ссылка ниже должна помочь. что касается параметра, я не уверен, но это может быть.
$.fn.ajax.success = function (){
///the rest goest here
}
Переопределить функцию jQuery.val()?