使用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并清除#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代码外部化为一个单独的文件 - 就像这样 - 基于http://starter.pixelgraphics.us/生成的jQuery插件代码
(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"
是否可以测试以这种方式编写的插件?
以另一种方式编写代码以使其更易于测试是否更好?
答案 0 :(得分:0)
这里有一些问题。首先,您将测试代码与查询代码的测试功能混合在一起。所以expect(result).toBeEmpty();
将测试这个$('#log').empty()
代码被调用,这是正确的测试,但它也测试该元素是空的,这不是你的工作。
其次,您在要测试的代码中创建新实例,使测试变得困难,导致您处理$
。毕竟,最好只测试你的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);
这样做你只能测试你的Tester,传入一些模拟而不是真正的DOM元素。看看sinon如何创建和使用模拟。因为我们在JavaScript世界中你也可以模拟JQuery,只是不要将jquery插入你的测试端,而是通过模拟替换它。