我正在为进行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调用的行为?
答案 0 :(得分:23)
这个问题有几年了,因为新版本的jQuery已经发生了一些变化。
要使用Jasmin执行此操作,您可以尝试Michael Falaga's approach
<强>解决方案强>
function ajax_response(response) {
var deferred = $.Deferred().resolve(response);
return deferred.promise();
}
使用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]);
});
});
没有茉莉花
$.ajax = ajax_response([1, 2, 3]);
$.ajax('GET', 'some/url/i/fancy').done(function(data) {
console.log(data); // [1, 2, 3]
});
答案 1 :(得分:14)
在阅读了@Robusto和@Val的启发之后,我发现了一种有效的方法:
//Mock ajax function
$.ajax = function (param) {
_mockAjaxOptions = param;
//call success handler
param.complete("data", "textStatus", "jqXHR");
};
我没有从任何真正的$ .ajax代码中引发事件或触发任何事件,而是让我的假ajax对象调用函数(作为参数传递给$.ajax()
)作为我假的一部分功能
答案 2 :(得分:11)
$.ajax
在尝试the accepted answer和the answer posted by user1634074之后,我设计了这两种简单灵活的混合方式。
以最基本的形式......
function ajax_response(response) {
return function (params) {
params.success(response);
};
}
$.ajax = ajax_response('{ "title": "My dummy JSON" }');
在上面的示例中,定义一个函数ajax_response()
,它接受一些JSON字符串作为参数(或任何数量的自定义参数,用于模拟响应)并返回一个匿名闭包函数,该函数将分配给{{ 1}}作为单元测试的覆盖。
匿名函数接受$.ajax
参数,该参数将包含传递给params
函数的设置对象。它使用传递给外部函数的参数来模拟来自服务器的响应。在这个例子中,它总是模拟来自服务器的成功响应,只需调用$.ajax
回调并为其提供虚拟JSON。
很容易重新配置......
success
下面我们可以看到它的实际效果......
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 */
答案 3 :(得分:4)
这里的答案很好,但是特别需要为单个API调用构建一个虚假的响应,同时保留所有其他API调用,直到后端服务构建完毕,这样我就可以继续在UI上构建内容。 / p>
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' }
]
}
});
};
答案 4 :(得分:1)
查看jQuery文档:您将看到Ajax设置提供了许多其他测试条件。如果你让它们都指向你的fakeAjaxSuccess,你可能会实现你的目标。
或者,将$.ajax
调用包装到自己的函数中并进行任何调用,只需使用fakeAjaxSuccess
对象调用事件处理程序。
答案 5 :(得分:1)
我认为以下链接应该有所帮助。至于参数,我不太确定,但可能是。
$.fn.ajax.success = function (){
///the rest goest here
}