关于单元测试jQuery的document.ready function()。
,我有一个问题目前我的代码中有两个场景:
function myFunction()
{
$(document).ready(function() { ... });
}
和
$(document).ready(function()
{
// some really long setup code here
});
我尝试为第一个场景编写单元测试,但我无法让它运行到document.ready函数中。至于第二种情况,我还没有想出一种方法来测试它(我很难找到测试它和语法的方法)。
假设我无法更改源代码,有没有办法测试这些功能? (假设测试它们是个好主意)
感谢。
答案 0 :(得分:6)
您不需要测试$(document).ready
,因为它是框架的一部分,并且已经过单元测试。在编写单元测试时,您需要测试两件事:
所以你真正需要做的是确保从$(document).ready
调用的代码是正确的。
function myInit(){
//...
}
function myFunction()
{
$(document).ready(myInit);
}
您现在需要做的就是单元测试myInit
功能。
您还可以做的是模拟$.ready
函数以确保您正在调用它:
var readyCalled = false;
$.ready = function(func){
readyCalled = (myInit == func);
}
//Your code containing `myInit` will get executed somewhere here
//....
//Then test:
test("Should have called ready", function() {
ok(readyCalled, "ready should have been called with myInit as a parameter.")
});
答案 1 :(得分:0)
注册on ready handler的函数应该注册另一个函数,而不是匿名代码块。然后,您可以测试与准备好的代码分开调用$ .ready()的代码。所以你有:
要测试方案1,您需要为jQuery注入一个测试双。这很难,就好像你重新定义$或jQuery一样,你可能会搞砸其他依赖它进行其他处理的代码(比如测试运行器)。同时,您的代码可能仍然希望在使用数组连接等实用程序方法时直接调用jQuery。任何反转控制模式都应解决这个问题(http://martinfowler.com/articles/injection.html)。
无论如何,这里有一些代码使用构造函数注入(使用JSMock作为模拟库,以及qunit(jQuery)用于测试运行器):
// the code
var createComponent = function(_$) {
var that = {};
that.OnStart = function() {
_$.ready(this.OnReady);
};
that.OnReady = function() {
};
return that;
};
// the test
test("OnStart associates the ready handler", function() {
var sut;
var mock$ = mc.createMock($);
mock$.expects().ready(isA.TypeOf(Function)).andStub(function(callback) {
equals(callback, sut.OnReady);
});
sut = createComponent(mock$);
sut.OnStart();
mc.verify();
});
test("OnReady does the right stuff", function() {
//etc
});
我将这种通用模式用于JS中的所有事件处理程序...您可能更喜欢使用原型类型。当您将函数作为参数传递给jQuery时,您需要注意在调用这些回调时jQuery不会设置“this”值。在测试中,这会因为equals(callback,sut.OnReady)不再通过而中断。要解决此问题,您需要使事件处理程序指向每个实例的成员。你可以想象什么时候有一些很好的工具可以获得一个列表,但这表明'OnReady'是一个不依赖'this'的成员。
var Component = function(_$) {
this._$ = _$;
// repeat for each event handler thats tested
this.OnReady = function() {
Component.prototype.OnReady.apply(this);
}
}
Component.prototype.Start = function() {
this._$.ready(this.OnReady);
}
Component.prototype.OnReady = function() {
}
答案 2 :(得分:0)