正如在这个jsFiddle中所看到的,我有一个函数"init",它配置了一个按钮,这样当单击时,它会打开一个进度对话框并发出Ajax调用。我想对这个JavaScript代码进行单元测试(使用QUnit),并检查以下情况:
- Ajax调用成功
- Ajax调用失败
我至少需要模拟Ajax调用和对window.open
的调用,以及我确信的其他调用,这取决于单元测试实现。
如何为测试这两种场景的代码编写QUnit单元测试?
编辑:需要测试的代码:
var statusmod = (function() {
var spinner = $("#spinner");
var init = function(id) {
var progressDialog = $("#progressdialog-content").dialog({
autoOpen: false,
title: "Launching Status Page"
});
var errorDialog = $("#errordialog-content").dialog({
autoOpen: false,
modal: true,
buttons: {
"OK": function() {
$(this).dialog("close");
}
}
});
var btn = $("#button-status");
btn.button().click(function() {
spinner.show();
progressDialog.dialog("open");
var url = $.validator.format("/api/binid/?id={0}", id);
// Call Web service to get binary ID
$.ajax({
url: url,
dataType: "json"
}).done(function(data) {
window.open($.validator.format("http://status/?Page=Status&Id={0}", data.Id), target = "_newtab");
}).fail(function(jqXHR, msg, errorThrown) {
errorDialog.dialog("open");
}).always(function() {
progressDialog.dialog("close");
});
return false;
});
};
return {
init: init,
_spinner: spinner
};
}());
我已经成功地为成功案例编写了一个QUnit测试,并为失败案例编写了另一个测试,正如您从这个jsFiddle中看到的那样。我使用Mockjax来伪造Ajax响应并模拟成功/失败的情况。值得注意的是,我将Ajax调用配置为同步的,这样我就可以编写同步测试,因为在异步Ajax回调启动后,我很难弄清楚如何运行测试。
我还利用Sinon.JS库来伪造依赖关系,并验证例如对话框是否正确启动。
下面包含了工作测试代码,请参阅我对测试中的函数(statusmod.init
)的问题。如果你认为我遗漏了什么,请告诉我。
var dialogSpy = null;
var windowSpy = null;
var id = "srcId";
var binId = "binId";
var url = $.validator.format("/api/binid/?id={0}", id);
var btnId = "#button-status";
module("Open status page", {
setup: function() {
// Allow us to run tests synchronously
$.ajaxSetup({
async: false
});
windowSpy = sinon.spy(window, "open");
dialogSpy = sinon.spy();
sinon.stub($.fn, "dialog", function() {
return {
"dialog": dialogSpy
};
});
statusmod.init(id);
},
teardown: function() {
windowSpy.restore();
$.fn.dialog.restore();
$.mockjaxClear();
// Remove click event handler for each test
$(btnId).unbind();
}
});
test("Successfully open status page", function() {
expect(4);
$.mockjax({
url: url,
contentType: "text/json",
responseText: {
Id: binId
}
});
var spinner = statusmod._spinner;
var spinnerSpy = sinon.spy(spinner, "show");
$(btnId).click();
ok(spinnerSpy.calledOnce, "Spinner shown");
ok(dialogSpy.withArgs("open").calledOnce, "Dialog opened");
ok(dialogSpy.withArgs("close").calledOnce, "Dialog closed");
equal(windowSpy.lastCall.args[0], $.validator.format("http://status/?Page=Status&Id={0}", binId), "Window opened");
});
test("Binary ID not found on server", function() {
expect(3);
$.mockjax({
url: url,
contentType: "text/json",
status: 404
});
$(btnId).click();
ok(dialogSpy.withArgs("open").calledTwice, "Dialogs opened");
ok(dialogSpy.withArgs("close").calledOnce, "Progress dialog closed");
ok(!windowSpy.called, "Window not launched");
});
首先,下载并包含Mockjax。
然后模拟您的ajax调用:
module("Mock Ajax", {
setup: function () {
/** this mocks the ajax call **/
$.mockjax({
url: 'yourUrl.php',
data: {'action': 'your',
'data': {
'that': 'you',
'send': 'here'
}
},
responseText:'{"your": ["returned":"json"],"string"}'
});
});
});
然后您可以在测试用例中进行ajax调用:
test( "Your testcase", function() {
$.ajax('yourUrl.php',
data: {'action': 'your',
'data': {
'that': 'you',
'send': 'here'
}
}, function(data) {
ok("do something with your data");
});
});
瞧,你已经成功地测试了一些东西!您可以向mockjax调用添加额外的参数(isTImeout、isError等)。文档可在此处找到。
这些都是基础知识,您可以使用文档对其进行编辑以满足您的需求,文档非常完整。