简体   繁体   English

在javascript中测试私有函数

[英]Testing private functions in javascript

I'm using the module pattern in Javascript to separate my public interface from the private implementation. 我在Javascript中使用模块模式将我的公共接口与私有实现分开。 To simplify what I'm doing, my code generates a chart. 为了简化我正在做的事情,我的代码生成了一个图表。 The chart consists of multiple parts (axises, labels, plot, legend, etc.) My code looks like: 该图表由多个部分(轴,标签,图,图例等)组成。我的代码如下所示:

var Graph = function() {
  var private_data;
  function draw_legend() { ... }
  function draw_plot() { ... }
  function helper_func() { ... }
  ...

  return {
    add_data: function(data) {
      private_data = data;
    },
    draw: function() {
      draw_legend()
      draw_plot()
    }
  }
}

Some people advocate only testing the public interface of your classes, which makes sense, but I'd really like to get in some tests to test each of the components separately. 有些人主张只测试你的类的公共接口,这是有道理的,但我真的想进行一些测试来分别测试每个组件。 If I screw up my draw_legend() function, I'd like that test to fail, not a test for the public draw() function. 如果我搞砸了我的draw_legend()函数,我希望测试失败,而不是公共draw()函数的测试。 Am I on the wrong track here? 我在这里走错了路吗?

I could separate each of the components in different classes, for example make a Legend class. 我可以将不同类中的每个组件分开,例如创建一个Legend类。 But it seems silly to create a class for what's sometimes just 5-10 lines of code, and it would be uglier because I'd need to pass in a bunch of private state. 但是,为有时只有5到10行代码创建一个类似乎很愚蠢,而且它会更加丑陋,因为我需要传递一堆私有状态。 And I wouldn't be able to test my helper functions. 而且我无法测试我的助手功能。 Should I do this anyway? 我还应该这样做吗? Should I suck it up and only test the public draw()? 我应该吸吮它,只测试公共抽奖()吗? Or is there some other solution? 还是有其他解决方案吗?

There is no way to access inner functions (private) from an outer scope. 无法从外部作用域访问内部函数(私有)。 If you want to test inner functions you might consider adding a public method for testing purposes only. 如果要测试内部函数,可以考虑添加公共方法以仅用于测试目的。 If you are using some sort of a build environment, for example ant, you may pre-process the javascript file for production and remove those test functions. 如果您正在使用某种构建环境,例如ant,您可以预处理javascript文件以进行生产并删除这些测试函数。

Actually Javascript is an Object oriented language. 实际上Javascript是面向对象的语言。 It's just not a statitcally typed one. 它不是一个类型化的类型。

My solution is just a little bit of hack. 我的解决方案只是一点点破解。 QUnit example: QUnit示例:

At the top of Qunit test html I have declared: 在Qunit测试html的顶部我声明:

var TEST_AVAILABLE = true;

In the testable class I have a fragment like this: 在testable类中,我有一个像这样的片段:

if(TEST_AVAILABLE){
   this.test={
      hasDraft:hasDraft,
      isInterpIdIn:isInterpIdIn,
      // other private methods
   };
}

In the QUnit you could verify 在QUnit中你可以验证

test( "hello booth", function() {
  var b = new Booth();
  ok(b);
  ok(b.test);
  ok(!b.test.hasDraft());
});

I have a similar problem. 我有一个类似的问题。 The solution I came up with is not something I like but it does the job and there's not a better solution I can find. 我提出的解决方案不是我喜欢的,但是它完成了工作并且找不到更好的解决方案。

function Graph()
{
    this.Test = function _Test(expressionStr) { return eval(expressionStr); }

    var private_data;
    function draw_legend() { ... }
    function draw_plot() { ... }
    function helper_func() { ... }
    ...
}

To test: 去测试:

var g = new Graph();
g.Test("helper_func()") == something;
g.Test("private_data") == something2

There is an easy way actually. 实际上有一种简单的方法。 You can use ajax to load the script and inject a function that exposes the private functions. 您可以使用ajax加载脚本并注入一个公开私有函数的函数。 I have an example here that uses qUnit and jQuery. 我在这里有一个使用qUnit和jQuery的例子。 But I'm sure the same can be easily accomplished using pure Javascript. 但我确信使用纯Javascript可以轻松完成同样的工作。

There is the only one right option: Different Builds for Testing and Production 只有一个正确的选择: 不同的测试和生产构建

1) mark development only parts 1)仅标记开发部分

/* test-code */
api._foo = foo
/* end-test-code */

2) strip them later... ;) 2)以后去除它们;;)

grunt.registerTask("deploy", 
  [
    "concat",
    "strip-code",
    ...

@philwalton has written beautiful articles: @philwalton撰写了精美的文章:

In an object oriented language, you would typically unit test the protected methods by having the test class inherit from the class it's testing. 在面向对象的语言中,您通常会通过让测试类继承其正在测试的类来对受保护的方法进行单元测试。

Of course, Javascript is not really an object oriented language, and this pattern does not allow for inheritance. 当然,Javascript实际上不是面向对象的语言,并且这种模式不允许继承。

I think you either need to make your methods public, or give up on unit testing them. 我认为你要么公开你的方法,要么放弃对它们进行单元测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM