如何在jquery插件中对私有方法进行单元测试?

时间:2011-04-21 22:04:48

标签: javascript jquery unit-testing jquery-plugins

也许这是一个新手JQuery问题,但是:

  • 正确的jquery插件写在闭包
  • 因此只能从外部访问定义插件接口的方法
  • 有时(或多次)可能需要帮助方法,因为它们作为插件接口的一部分公开是没有意义的(例如因为它们改变了内部状态)。
  • 如何进行单元测试?

例如,查看blockUI插件,方法如何安装,删除,重置获得单元测试?

要在Java中绘制并行,我会:

  1. 创建一个仅包含公共方法的BlockUI接口(按定义)
  2. 创建一个实现上述接口的BlockUIImpl类。此类将包含install(),remove(),reset()方法,这些方法可以是公共的,或(包)受保护的
  3. 所以,我会对Impl进行单元测试,但客户端程序员会通过BlockUI接口与插件进行交互。

3 个答案:

答案 0 :(得分:13)

这同样适用于任何其他语言和测试私有:要测试私有方法,您应该通过公共接口来练习它们。换句话说,通过调用公共方法,私有方法在流程中得到测试,因为公共方法依赖于私有方法。

一般来说私有方法不是与公共接口分开测试的 - 整点是它们是实现细节,测试通常不应该对实现的具体细节有太多了解。

答案 1 :(得分:2)

在JavaScript中的函数内部编写的代码,或者在调用它时的 closure ,不一定与该函数的外部隔离。

知道函数可以看到定义它们的范围是很有用的。您创建的任何闭包都包含包含它的代码的范围,因此也包含函数。

这个带有jQuery插件和人工“命名空间”的简单示例可能有助于证明这一假设:

// Initialise this only when running tests
my_public_test_namespace = function(){};

jQuery.fn.makeItBlue = function() {

    makeItBlue(this);

    function makeItBlue(object) {
        object.css('color','blue');
    }

    if(typeof my_public_test_namespace != "undefined") {
        my_public_test_namespace.testHarness = function() {
            return {
                _makeItBluePrivateFn: makeItBlue
            }
        };
    }
};

$("#myElement").makeItBlue(); // make something blue, initialise plugin

console.debug(my_public_test_namespace.testHarness()._makeItBluePrivateFn);

但不要忘记你不应该真的测试私人。 ;)

答案 2 :(得分:0)

我想出了同样的问题,在浏览并找到不适用的答案之后,我最终解决了类似的问题。

问题:“我有一个小部件,它有一个我想要测试的行为,以确保它按预期工作,一些方法在内部调用,因为他们必须解决内部行为,公开他们作为公共没有意义,因为他们不会从外面调用,测试公共方法意味着你不会测试小部件的内部,所以最后我能做什么?“

解决方案:“Creata一个测试小部件,它公开了您感兴趣的测试方法,并在qunit中使用它们,这是一个例子:”

// Namespaces to avoid having conflicts with other things defined similarly
var formeditortest = formeditortest || {};
// widget that inherits from the container I want to test
$.widget( "app.testcontainer", $.app.container,  {
    executeDrop: function(drop, helper) {
       var self = this;
       self._executeDrop(drop, helper);
    }
});
// Test cases
formeditortest.testDropSimple = function(assert) {
   var container = $("<div />");
   container.testcontainer();
   container.testcontainer("drop", 0, 3);
   assert.equal(true, $(innerDiv.children()[0]).hasClass("droparea"));
});

QUnit.test(name, function( assert ) {
   formeditortest.testDropSimple(assert);
   formeditortest.testDropBottom(assert);
});

使用这种方法,继承的testcontainer可以进行测试元素所需的准备工作,然后qunit将处理测试,这解决了我的问题,希望这适用于遇到麻烦的其他人接受这类测试。

评论家?欢迎发表评论,如果我做些傻话,我想改进这个!!!