如何用Jasmine测试JQuery插件?

问题描述:

用Jasmine对JQuery代码进行单元测试的最佳方法是什么?如何用Jasmine测试JQuery插件?

我有这个简单的jQuery的测试程序:

<div id='log'>log goes here</div> 
<button id='btnClearLog'>Clear log</button> 
<button id='btnAddLog'>Add log</button> 

<script> 
$(document).ready(function() { 

    $('#log').empty(); 

    $('#btnClearLog').click(function() { 
     $('#log').empty(); 
    }); 

    $('#btnAddLog').click(function() { 
     $('#log').append("<br />something");  
    }); 
}); 
</script> 

可正常工作 - DIV#日志为空文件时的负荷,增加点击时#log和明确#log。

但我不认为这是可能的单元测试,因为JQuery代码是在HTML页面内。

所以,我重新写这样的:

<div id='log'>log goes here</div> 
<button id='btnClearLog'>Clear log</button> 
<button id='btnAddLog'>Add log</button> 

<script> 
$(document).ready(function() { 

    $('#log').tester(); 

}); 
</script> 

,并外在jQuery代码到一个单独的文件 - 像这样 - 基于生成的jQuery插件代码http://starter.pixelgraphics.us/

(function($){ 

    $.Tester = function(el){ 

    var base = this; 

      base.init = function(){ 

     $('#log').empty(); 

     $('#btnClearLog').click(function() { 
      base.clear(); 
     }); 

     $('#btnAddLog').click(function() { 
      base.add(); 
     }); 
      }; 

    base.clear = function(){ 
     $('#log').empty(); 
      }; 

    base.add = function(){ 
     $('#log').append("<br />something"); 
      }; 

      base.init(); 
    }; 

    $.fn.tester = function(){ 
     return this.each(function(){ 
      (new $.Tester(this)); 
     }); 
    }; 

})(jQuery); 

这也符合预期。

但是,我试图在Jasmine脚本不起作用。

describe('tester', function() { 

    it('log should be empty', function() { 
     var log = "<div id='log'>log</div>"; 
     var result = $(log).tester(); 
     expect(result).toBeEmpty(); 
    } 

}); 

我已经试过以上的各种排列 - 所有失败:

"Expected '<div id="log">log</div>' to be empty" 

是否有可能测试这种写法的插件吗?

以另一种方式编写代码以使其更易于测试是否更好?

这里有一些问题。首先,将测试代码与查询代码的测试功能混合使用。因此,expect(result).toBeEmpty();将测试这段代码被调用,这是正确的测试,但它也测试元素是空的,这不是你的工作。

其次,你在你想要测试的代码中创建新的实例,是什么让它很难测试,因为你已经处理了$。所以,毕竟这将是只有更好,以测试你的Tester()功能和插入的所有元素对想:

(function($){ 

    $.Tester = function(el, log, btnClearLog, btnAddLog){ 

    var base = this; 

      base.init = function(){ 

     log.empty(); 

     btnClearLog.click(function() { 
      base.clear(); 
     }); 

     btnAddLog.click(function() { 
      base.add(); 
     }); 
      }; 

    base.clear = function(){ 
     log.empty(); 
      }; 

    base.add = function(){ 
     log.append("<br />something"); 
      }; 

      base.init(); 
    }; 

    $.fn.tester = function(){ 
     return this.each(function(){ 
      (new $.Tester(this, $('#log'), $('#btnClearLog'), $('#btnAddLog'))); 
     }); 
    }; 

})(jQuery); 

这样做,所以你可以测试只有你测试仪,通过在一些嘲笑,而不是真正的DOM元素。看看如何创建和使用mock的sinon。正如我们在JavaScript世界中一样,你也可以嘲笑JQuery,简单地说不要将jquery插入你的测试端,而是通过模拟替代它。