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 的原始版本。

The example above is of course simplified but there are plenty of scenarios I can think of where it would be convenient to unit test conditional paths through a method.

Is this a limitation of the revealing module pattern or simply a misuse of unit testing? If not what work-arounds are available to me? I'm considering moving to something like RequireJS or reverting back to non-modular code.

Any advice appreciated!

4

2 回答 2

9

You cant test the intern methodes of a closure. And you also shouldn't spy on it. Think about about your module as a black box. You put something in and you get something out. All you should test is that the thing you get out of your module is the one that you expect.

Spying on methodes in your module makes not much sense. Think about it. You spy on it, the test passes. Now you change the functionality so it creates a bug, the test still passes cause the function is still called but you never mention the bug. If you just test the thing that cames out you dont need to spy on internal methodes cause, that they are called is implicite when the outcome of the module is what you expect.

So in your case there is no thing that goes in and nothing comes out. This makes not much sense but I believe that your module interacts with DOM or makes an ajax call. This are things that you can test (DOM) or you should spy on (ajax).

You should also make you self familiar with Inversion of Control and Dependency Injection. These are patterns that will make your modules much more easier to test.

于 2013-06-15T09:18:52.933 回答
0

If you use the keyword "this" when you call publicMethodB() from publicMethodA() it will work. For example:

var myWonderfulModule = (function () {
    function publicMethodA (condition) {
        if(condition === 'b') {
            this.publicMethodB();
        }
    }

    function publicMethodB () {
        // ...
    }

    return {
        methodA : publicMethodA,
        methodB : publicMethodB
    }
}());
于 2016-06-30T22:38:09.590 回答