如何在jQuery插件中对内部函数进行单元测试?

6
在一个我创建的jQuery插件中,我已经创建了一些辅助函数,例如:
(function($) {

  var someHelperFunction = function(s, d) {
    return s*d;
  }
  var someOtherHelperFunction = function(s) {
    return s*2;
  }

// here goes the normal plugin code

})(jQuery);

现在我想从外部调用someHelperFunction,以便能够对其进行单元测试,有什么办法可以实现吗?


由于您无法从外部访问方法,因此这是不可能的。 - Felix Kling
5个回答

2
根据相关问题,我建议只测试外部接口。但如果你必须在隔离环境中测试这些方法,你需要在它们作为内部方法的上下文之外测试它们的“副本”。换句话说,在一个对象中创建这些方法,使它们对客户端代码不可访问,然后将这些版本与你的外部脚本结合起来进行预处理。听起来很麻烦,但这就是隐藏方法的目的,对吧?(使它们无法被访问。)

1

如果内部函数需要测试,那么这表明它们可能应该在某个单独的模块中,并作为依赖项注入并在对象的公共接口实现中使用。这是更“可测试”的做法。

var myActualImplementationTestTheHellOutOfMe = function(s, d) {

    return s*d;

}

(function($, helper) {

  var someHelperFunction = function(s, d) {
    return helper(s, d);
  }
  var someOtherHelperFunction = function(s) {
    return s*2;
  }

// here goes the normal plugin code

})(jQuery, myActualImplementationTestTheHellOutOfMe);

1

您可能还想考虑 JavaScript doctests。 我知道有两种实现:Ian Bicking的doctest.js和我自己的doctest


我试图权衡每个库的利弊,但它们看起来非常相似。作为doctest的作者,您能否简要介绍一下?我的使用案例是将单元测试添加到white-space,它没有公共API,需要测试HTML fixtures和document.readyState。 - dotnetCarpenter
首先,doctest 允许测试使用示例,确保它们保持最新。Doctest 实际上是用于测试文档而不是代码。其次,doctest 对于纯函数非常有效,但对于基于回调的代码则不然。我建议使用专门的测试框架。 - davidchambers
我真正喜欢 doctest 的原因是,我不必为了测试而人为地创建公共 API。据我所知,我可以在闭包内编写方法/函数文档,并仍然允许单元测试访问。我想这就是纯函数的限制对我来说是个致命伤,因为我真正测试的是浏览器行为。 - dotnetCarpenter

0

helpers 是在插件内部作用域中定义的,这是一个匿名函数,你无法访问其中声明的变量。
如果你想要测试它,可以在函数前面去掉 var 关键字。这将把函数声明为全局函数(会将它们附加到 window 对象上),使它们能够从 window 作用域中可见(通过调用 someHelperFunctionwindow.someHelperFunction)。
因此,进行测试:

(function($) {
    someHelperFunction = function(s, d) {
        return s*d;
    }
    someOtherHelperFunction = function(s) {
        return s*2;
    }
     // here goes the normal plugin code
})(jQuery);

测试结束后,再次添加var关键字。

更新
我认为更好的方法是将可测试的函数分组到一个对象中,并构建一个 API。然后,在同样的原则下,您可以将该 API 在全局范围内或不可见:

(function($, global) {
    someHelperFunction = function(s, d) {
        return s*d;
    }
    someOtherHelperFunction = function(s) {
        return s*2;
    }

    var api = {
        someHelperFunction: someHelperFunction,
        someOtherHelperFunction: someOtherHelperFunction
    };

    // decide whether you want to expose your api or not 
    if(makeGlobal) {
        global.api = api;
    }
})(jQuery, this);

3
不要使用全局变量来测试私有函数。这并不是一个好答案,因为它支持不良实践。 - drublic

-3

看一下qunit,一个JavaScript单元测试库


1
这不是关于一般的测试,而是关于测试本地方法。 - Felix Kling
抱歉,我说话太快了。自己注意:在打字之前要仔细阅读。 - cander

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接