揭示模块模式 - 使用Jasmine进行单元测试

9
在短暂地尝试了透明模块模式后,我发现在测试模块时存在一些问题。然而我无法确定这是我的测试方法的问题还是有某种解决方法。
请考虑以下代码:
var myWonderfulModule = (function () {
  function publicMethodA (condition) {
    if(condition === 'b') {
      publicMethodB();
    }
  }

  function publicMethodB () {
    // ...
  }

  return {
    methodA : publicMethodA,
    methodB : publicMethodB
  }
}());

如果我想要测试(使用Jasmine)通过publicMethodA到达publicMethodB的各种路径,我可以编写一个小测试如下所示:
it("should make a call to publicMethodB when condition is 'b'", function() {
  spyOn(myWonderfulModule , 'publicMethodB');
  myWonderfulModule.publicMethodA('b');
  expect(myWonderfulModule.publicMethodB).toHaveBeenCalled();
});

如果我理解正确,闭包内有一个不能更改的publicMethodB的副本。即使我在之后更改了myWonderfulModule.publicMethodB:

myWonderfulModule.publicMethodB = undefined;

调用myWonderfulModule.publicMethodA仍然会运行原始版本的B。

当然,上面的示例是简化的,但我可以想到许多情况,在这些情况下,通过方法进行条件路径的单元测试将非常方便。

这是透露模块模式的局限性还是单元测试的误用?如果不是,有哪些解决方法可供我使用?我正在考虑转向类似RequireJS的东西或恢复回非模块化代码。

任何建议都将不胜感激!

2个回答

9
你不能测试闭包的内部方法,也不应该对其进行监视。将模块视为黑盒子,输入一些东西,得到一些东西。你应该测试的只是从模块中获取的内容是否符合预期。
在模块中监视方法没有太多意义。想想看,你对其进行监视,测试通过了。现在你更改功能以创建一个 bug,测试仍然通过,因为函数仍然被调用,但你从未提到 bug。如果你只测试输出的结果,就不需要监视内部方法,因为当模块的输出符合预期时,它们会被隐式调用。
因此,在你的情况下,没有任何东西进去,也没有任何东西出来。这没有太多意义,但我相信你的模块与 DOM 交互或进行 ajax 调用。这些都是可以测试(DOM)或应该监视(ajax)的事情。
你还应该熟悉控制反转和依赖注入。这些模式将使你的模块更容易测试。

0
如果你在从publicMethodA()调用publicMethodB()时使用关键字"this",它将起作用。例如:
var myWonderfulModule = (function () {
    function publicMethodA (condition) {
        if(condition === 'b') {
            this.publicMethodB();
        }
    }

    function publicMethodB () {
        // ...
    }

    return {
        methodA : publicMethodA,
        methodB : publicMethodB
    }
}());

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