在与揭示模块模式的短暂浪漫之后,我开始意识到单元测试模块的挫折。然而,我无法决定是否是我测试模块的方法或是否存在某种形式的解决方法。
请考虑以下代码:
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或恢复非模块化代码。
任何建议表示赞赏!
答案 0 :(得分:8)
你无法测试一个闭包的实习方法。你也不应该窥探它。把你的模块想象成一个黑盒子。你把东西放进去,你得到了一些东西。您应该测试的是,您从模块中获得的东西是您期望的那个。
对模块中的方法进行间谍活动没有多大意义。想一想。你监视它,测试通过。现在你改变了功能,所以它创建了一个bug,测试仍然通过,因为仍然调用了该函数,但你从未提到过这个bug。如果你只是测试出来的东西,你就不需要监视内部的方法,因为当模块的结果符合你的期望时,它们被称为隐含的。
所以在你的情况下,没有东西进入,没有任何东西出来。这没什么意义,但我相信你的模块与DOM交互或进行ajax调用。这是你可以测试的东西(DOM),或者你应该监视(ajax)。
您还应该让自己熟悉Inversion of Control and Dependency Injection。这些模式将使您的模块更容易测试。
答案 1 :(得分:0)
如果您使用关键字"此"当你从publicMethodA()调用publicMethodB()时,它将起作用。例如:
var myWonderfulModule = (function () {
function publicMethodA (condition) {
if(condition === 'b') {
this.publicMethodB();
}
}
function publicMethodB () {
// ...
}
return {
methodA : publicMethodA,
methodB : publicMethodB
}
}());