我正在尝试使用 Jasmine 为基本的 jQuery AJAX 请求编写一些 BDD 规范。我目前在独立模式下使用 Jasmine(即通过
SpecRunner.html
)。我已将 SpecRunner 配置为加载 jquery 和其他 .js 文件。为什么以下不起作用的任何想法? has_returned 不会变为真,甚至认为“雅皮士!”警报显示正常。
describe("A jQuery ajax request should be able to fetch...", function() {
it("an XML file from the filesystem", function() {
$.ajax_get_xml_request = { has_returned : false };
// initiating the AJAX request
$.ajax({ type: "GET", url: "addressbook_files/addressbookxml.xml", dataType: "xml",
success: function(xml) { alert("yuppi!"); $.ajax_get_xml_request.has_returned = true; } });
// waiting for has_returned to become true (timeout: 3s)
waitsFor(function() { $.ajax_get_xml_request.has_returned; }, "the JQuery AJAX GET to return", 3000);
// TODO: other tests might check size of XML file, whether it is valid XML
expect($.ajax_get_xml_request.has_returned).toEqual(true);
});
});
如何测试回调是否被调用?非常感谢任何指向与使用 Jasmine 测试异步 jQuery 相关的博客/材料的指针。
我猜你可以做两种类型的测试:
这里是一个示例,说明如何伪造 AJAX 请求,然后编写单元测试来验证伪造的 AJAX 请求是否转到正确的 URL:
it("should make an AJAX request to the correct URL", function() {
spyOn($, "ajax");
getProduct(123);
expect($.ajax.mostRecentCall.args[0]["url"]).toEqual("/products/123");
});
function getProduct(id) {
$.ajax({
type: "GET",
url: "/products/" + id,
contentType: "application/json; charset=utf-8",
dataType: "json"
});
}
对于
Jasmine 2.0,请改用:
expect($.ajax.calls.mostRecent().args[0]["url"]).toEqual("/products/123");
如这是一个类似的单元测试,用于在 AJAX 请求成功完成后验证您的回调是否已执行:
it("should execute the callback function on success", function () {
spyOn($, "ajax").andCallFake(function(options) {
options.success();
});
var callback = jasmine.createSpy();
getProduct(123, callback);
expect(callback).toHaveBeenCalled();
});
function getProduct(id, callback) {
$.ajax({
type: "GET",
url: "/products/" + id,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: callback
});
}
对于
Jasmine 2.0,请改用:
spyOn($, "ajax").and.callFake(function(options) {
如最后,您在别处暗示您可能想要编写发出真正 AJAX 请求的集成测试 - 用于集成目的。这可以使用 Jasmine 的异步功能来完成:waits()、waitsFor() 和 runs():
it("should make a real AJAX request", function () {
var callback = jasmine.createSpy();
getProduct(123, callback);
waitsFor(function() {
return callback.callCount > 0;
});
runs(function() {
expect(callback).toHaveBeenCalled();
});
});
function getProduct(id, callback) {
$.ajax({
type: "GET",
url: "data.json",
contentType: "application/json; charset=utf-8"
dataType: "json",
success: callback
});
}
http://github.com/pivotal/jasmine-ajax.
它是一个插入式帮助器(对于 jQuery 或 Prototype.js)在 XHR 层存根,因此请求永远不会消失。然后你可以期待所有你想要的请求。然后它允许您为所有情况提供夹具响应,然后为您想要的每个响应编写测试:成功、失败、未经授权等。
它将 Ajax 调用带出异步测试领域,并为您提供了很大的灵活性来测试您的实际响应处理程序应该如何工作。
var app = {
fire: function(url, sfn, efn) {
$.ajax({
url:url,
success:sfn,
error:efn
});
}
};
一个示例测试套件,它将根据 url regexp 调用回调
describe("ajax calls returns", function() {
var successFn, errorFn;
beforeEach(function () {
successFn = jasmine.createSpy("successFn");
errorFn = jasmine.createSpy("errorFn");
jQuery.ajax = spyOn(jQuery, "ajax").andCallFake(
function (options) {
if(/.*success.*/.test(options.url)) {
options.success();
} else {
options.error();
}
}
);
});
it("success", function () {
app.fire("success/url", successFn, errorFn);
expect(successFn).toHaveBeenCalled();
});
it("error response", function () {
app.fire("error/url", successFn, errorFn);
expect(errorFn).toHaveBeenCalled();
});
});
因此,要验证回调函数已在您的 AJAX 请求中调用,您需要创建一个间谍,向其添加一个 callFake 函数,然后使用该间谍作为您的回调函数。事情是这样的:
describe("when you make a jQuery AJAX request", function()
{
it("should get the content of an XML file", function(done)
{
var success = jasmine.createSpy('success');
var error = jasmine.createSpy('error');
success.and.callFake(function(xml_content)
{
expect(success).toHaveBeenCalled();
// you can even do more tests with xml_content which is
// the data returned by the success function of your AJAX call
done(); // we're done, Jasmine can run the specs now
});
error.and.callFake(function()
{
// this will fail since success has not been called
expect(success).toHaveBeenCalled();
// If you are happy about the fact that error has been called,
// don't make it fail by using expect(error).toHaveBeenCalled();
done(); // we're done
});
jQuery.ajax({
type : "GET",
url : "addressbook_files/addressbookxml.xml",
dataType : "xml",
success : success,
error : error
});
});
});
我已经完成了成功函数和错误函数的技巧,以确保即使您的 AJAX 返回错误,Jasmine 也会尽快运行规范。
如果你没有指定一个错误函数并且你的 AJAX 返回一个错误,你将不得不等待 5 秒(默认超时间隔)直到 Jasmine 抛出一个错误
Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
。您还可以像这样指定自己的超时时间:
it("should get the content of an XML file", function(done)
{
// your code
},
10000); // 10 seconds
jasmine-ajax
库。这个库提供了一组函数和匹配器,允许您在 Jasmine 测试中模拟 AJAX 请求和响应。这里是一个如何使用 Jasmine 验证 jQuery AJAX 请求的例子:
describe('my AJAX request', function() {
beforeEach(function() {
jasmine.Ajax.install();
});
afterEach(function() {
jasmine.Ajax.uninstall();
});
it('should make an AJAX request to the correct URL', function() {
// Set up the request
var xhr = new XMLHttpRequest();
xhr.open('GET', '/my-api');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
console.log('success!');
}
};
xhr.send();
// Verify the request
expect(jasmine.Ajax.requests.mostRecent().url).toBe('/my-api');
expect(jasmine.Ajax.requests.mostRecent().method).toBe('GET');
expect(jasmine.Ajax.requests.mostRecent().requestHeaders['Content-Type']).toBe('application/json');
});
});
在这个例子中,我们首先在jasmine-ajax
块中安装
beforeEach
库。然后,我们在
it
块中设置一个基本的 jQuery AJAX 请求。最后,我们使用
jasmine.Ajax.requests.mostRecent()
函数检索最近的 AJAX 请求,然后使用
expect
函数验证请求具有正确的 URL、方法和标头。您还可以使用
jasmine.Ajax.requests.filter
函数根据其 URL、方法或标头检索特定的 AJAX 请求。此外,您可以使用
jasmine.Ajax.requests.count
函数来检查在测试期间发出了多少 AJAX 请求。