创建可单元测试的闭包的最佳模式?

时间:2016-05-26 06:28:32

标签: javascript unit-testing closures

鉴于此:

var closure = (function() {
    var some_variable;
    var ret = {};

    function some_internal_function() {
        return some_variable;
    };

    function init() {
        some_variable = document.getElementById("canvas");
    }

    ret.some_internal_function = some_internal_function;

    return ret;
}());

我希望能够在单元测试期间some_variable到模拟对象。但这似乎是不可能的。 There used to be a work around with eval(),但这似乎不再可能了。

我假设我必须劫持我的init()函数来制作我想要的模拟,但这似乎与单元测试哲学相反,因为我基本上依赖于另一个函数的执行来决定我想测试的人的行为!

我已经看到一些代码在可执行的上下文中传递以在函数执行期间使用,我认为这与测试/获取内部变量有关。

我想我可以分叉一个新的节点进程node -e closure.toString(),将字符串修改为var some_variable = {}; //the mock object,附加一个方法来返回值(console.log(closure.some_internal_function())),将结果反馈给我主要过程并使用qunit执行assert()。但这似乎是试图成为英雄,当应该有更好的方式(如果有任何看起来比this way><)更容易。

有更好的方法吗?测试此类事物的最佳模式是什么?

2 个答案:

答案 0 :(得分:1)

更好的方法是不使用匿名模块模式。请考虑以下事项:

var closure = aNameThatConveysWhatYourThingIs(document.getElementById("canvas"));

function aNameThatConveysWhatYourThingIs(some_variable) {
  var ret = {};

  function some_internal_function() {
      return some_variable;
  };

  ret.some_internal_function = some_internal_function;

  return ret;
}

这不需要特技来实现dependency injection,这就是你正在努力的目标。

然后,您可以在测试中简单地使用模拟依赖项调用该函数,以便访问并对正在操作的状态进行断言。

使用匿名模块模式:

  • 获取依赖关系,而不是要求它们。
  • 将模块中的代码与其父作用域紧密结合。

结果是:

  • 很难控制代码操纵的状态,你必须聪明才能做到这一点,而不是仅仅支持它。
  • 很难将代码与编写代码的上下文分开。

这些特性是对匿名模块模式所固有的可测试性的避免。使用它似乎不符合您对代码的期望。

答案 1 :(得分:1)

只是更完整一点:

http://superherojs.com/