【问题标题】:how to unit-test private methods in jquery plugins?如何对 jquery 插件中的私有方法进行单元测试?
【发布时间】:2011-08-10 15:40:31
【问题描述】:

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

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

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

为了画一个平行线,在 Java 中我会:

  1. 创建仅包含公共方法的 BlockUI 接口(根据定义)
  2. 创建一个实现上述接口的 BlockUIImpl 类。此类将包含可能是公共的或(包)受保护的 install()、remove()、reset() 方法

因此,我将对 Impl 进行单元测试,但客户端程序员将通过 BlockUI 接口与插件进行交互。

【问题讨论】:

标签: javascript jquery unit-testing jquery-plugins


【解决方案1】:

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

通常私有方法不会与公共接口分开测试 - 重点是它们是实现细节,测试通常不应该对实现的细节了解太多。

【讨论】:

  • 好的,足够公平:私有方法本身。但是,有什么方法可以模仿我提到的接口/实现类方法?
  • 根据我的经验,在 JS 中尝试模仿 Java 或类似的东西没有多大意义,因为它通常只会让事情变得更复杂而没有任何好处......如果您希望将某些方法标记为私有,通常通过使用 JSDoc 注释或在名称前加下划线来完成。
  • 感谢您的回复,贾尼。尽管如此,我认为我没有很好地解释我试图实现的好处。取blockUI插件中的'remove'功能:github.com/malsup/blockui/blob/master/jquery.blockUI.js
  • 关键是你不测试私人。如果公共方法正常工作,那么您可以假设私有方法也正常工作。如果私有方法有问题,那么公共方法也无法正常工作。
  • @JaniHartikainen 这很有意义。另外,编写测试非常无聊。越少我必须问心无愧地写越好。
【解决方案2】:

编写在 JavaScript 函数中的代码,或您所称的 closure,不一定与该函数的外部隔离。

知道函数具有定义它们的范围的可见性是很有用的。您创建的任何闭包都带有包含它的代码的作用域和函数。

这个带有 jQ​​uery 插件和人工“命名空间”的简单示例可以用来证明这个假设:

// 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);

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

【讨论】:

  • 你能解释一下为什么你不应该测试私有函数吗?我认为它对于复杂的代码和/或回归测试非常有用。
  • 嗨 Sjeiti。这在 Jani 的回答中得到了解释。也许您打算对该答案发表评论。干杯
【解决方案3】:

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

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

解决方案:“创建一个测试小部件,公开您感兴趣的测试方法并在 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);
});

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

批评者?欢迎评论,如果我在做一些傻事,我想改进它!!!

【讨论】:

    猜你喜欢
    • 2010-09-20
    • 2018-08-01
    • 2022-11-30
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-11
    相关资源
    最近更新 更多