Jam*_*ice 6 javascript unit-testing qunit
我们正在尝试为JS重型Web应用程序实现QUnit JavaScript测试.我们正在努力寻找成功测试涉及jQuery AJAX请求的方法的方法.例如,我们有以下构造函数(显然这是一个非常简单的例子):
var X = function() {
this.fire = function() {
$.ajax("someURL.php", {
data: {
userId: "james"
},
dataType: "json",
success: function(data) {
//Do stuff
}
});
};
};
var myX = new X();
myX.fire();
Run Code Online (Sandbox Code Playgroud)
我们正试图找到一种方法来测试该fire方法,最好是使用存根URL而不是真实的URL someURL.php.
目前唯一明显的解决方案是将URL和success回调添加为构造函数的参数.这样,在测试中,我们可以创建一个新的实例X并传入存根URL,并在存根返回响应时运行一个回调.例如:
test("Test AJAX function", function() {
stop();
var myX = new X();
//Call the AJAX function, passing in the stub URL and success callback
myX.fire("stub.php", function(data) {
console.log(data);
start();
});
});
Run Code Online (Sandbox Code Playgroud)
但是,这似乎不是一个非常好的解决方案.有没有更好的办法?
使用jQuery,您可以使用.ajax()作为promise返回的xhr对象,因此您可以添加更多处理程序(请参见下文),而不仅仅是单个success,complete以及error您在选项中定义的处理程序.因此,如果异步函数可以返回xhr对象,则可以添加特定于测试的处理程序.
至于URL,这有点棘手.我有时在localhost上设置一个非常简单的Node服务器,它只提供从真实服务器复制的预设响应.如果您在相同的服务器上运行测试套件,则您的URL只需要是命中测试服务器而不是生产服务器的绝对路径.当服务器看到它们时,您还会获得请求本身的记录.或者,如果您想查看代码如何处理它,您可以让测试服务器故意发回错误或错误响应.
但这当然是一个非常复杂的解决方案.更容易的是在您可以从测试套件重新定义URL的位置定义URL.例如:
/* in your code */
var X = function () {
this.fire = function () {
return $.ajax({ url: this.constructor.url, ... });
};
};
X.url = "someURL.php"; // the production url
/* in your tests */
X.url = "stub.php"; // redefine to the test url
Run Code Online (Sandbox Code Playgroud)
此外,QUnit有一个asyncTest功能,它需要stop()你.添加一个小帮手来跟踪何时重新开始,你有一个很好的解决方案.
这是我以前做过的
// create a function that counts down to `start()`
function createAsyncCounter(count) {
count = count || 1; // count defaults to 1
return function () { --count || start(); };
}
// ....
// an async test that expects 2 assertions
asyncTest("testing something asynchronous", 2, function() {
var countDown = createAsyncCounter(1), // the number of async calls in this test
x = new X;
// A `done` callback is the same as adding a `success` handler
// in the ajax options. It's called after the "real" success handler.
// I'm assuming here, that `fire()` returns the xhr object
x.fire().done(function(data, status, jqXHR) {
ok(data.ok);
equal(data.value, "foobar");
}).always(countDown); // call `countDown` regardless of success/error
});
Run Code Online (Sandbox Code Playgroud)
基本上countDown是一个函数,从你指定的任何东西倒数到零,然后调用start().在这种情况下,有1个异步调用,因此countDown将从中倒数.当ajax调用完成时,无论它如何运行,它都会这样做,因为它被设置为always回调.
并且因为asyncTest被告知期望2个断言,如果.done()从不调用回调,它将报告错误,因为不会运行断言.因此,如果通话完全失败,您也会知道.如果要记录错误的内容,可以.fail()向promise链添加回调.