单元测试jQuery document.ready函数

时间:2009-11-26 00:07:25

标签: javascript jquery unit-testing

关于单元测试jQuery的document.ready function()。

,我有一个问题

目前我的代码中有两个场景:

function myFunction()
{
    $(document).ready(function() { ... });
}

$(document).ready(function()
{
    // some really long setup code here
});

我尝试为第一个场景编写单元测试,但我无法让它运行到document.ready函数中。至于第二种情况,我还没有想出一种方法来测试它(我很难找到测试它和语法的方法)。

假设我无法更改源代码,有没有办法测试这些功能? (假设测试它们是个好主意)

感谢。

3 个答案:

答案 0 :(得分:6)

您不需要测试$(document).ready,因为它是框架的一部分,并且已经过单元测试。在编写单元测试时,您需要测试两件事:

  1. 您与框架的互动。这包括确保使用正确的参数调用正确的函数。
  2. 您自己的代码 - 您的代码是正确的。
  3. 所以你真正需要做的是确保从$(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. 验证正确功能的一个测试被设置为就绪处理程序
  2. 验证就绪处理程序的另一个测试是做正确的事情
  3. 要测试方案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)

要回答此问题,请参阅帖子herehere