主持人注:这里已经有39个答案了(有些已经删除了)。在你发表你的答案之前,考虑一下你是否可以为讨论添加一些有意义的东西。你很可能只是在重复别人已经说过的话。


我偶尔发现自己需要将类中的私有方法设为public,只是为了为它编写一些单元测试。

通常这是因为该方法包含类中其他方法之间共享的逻辑,并且单独测试逻辑更整洁,或者另一个原因可能是我想测试同步线程中使用的逻辑,而不必担心线程问题。

其他人发现他们这样做是因为我不喜欢吗?我个人认为,公开一个方法的好处超过了它在类之外没有提供任何服务的问题……

更新

谢谢大家的回答,似乎引起了大家的兴趣。我认为普遍的共识是测试应该通过公共API进行,因为这是使用类的唯一方式,我非常同意这一点。在我上面提到的几个案例中,我会这样做,这是不常见的情况,我认为这样做的好处是值得的。

然而,我可以看到,每个人都指出它不应该真的发生。再仔细想想,我觉得改变你的代码来适应测试是一个坏主意——毕竟我认为测试在某种程度上是一个支持工具,而改变一个系统来“支持一个支持工具”是明显的坏做法。


当前回答

首先查看是否应该将该方法提取到另一个类中并将其设为public。如果不是这样的话,将其设置为包保护,并在Java中使用@VisibleForTesting进行注释。

其他回答

您希望单独测试的私有方法表明在您的类中隐藏了另一个“概念”。将这个“概念”提取到它自己的类中,并将其作为一个单独的“单元”进行测试。

看看这个关于这个话题的有趣视频。

在您的更新中,您说使用公共API进行测试很好。 这里实际上有两所学校。

黑盒测试 黑盒学派认为,类应该被视为一个黑盒,没有人可以看到其中的实现。测试这一点的唯一方法是通过公共API——就像类的用户将使用它一样。 白盒测试。 白盒学派认为自然地使用关于类实现的知识,然后测试类以了解它应该工作。

在这次讨论中我真的不能支持任何一方。我只是想知道有两种不同的方法来测试一个类(或库或其他)会很有趣。

Guava有一个@VisibleForTesting注释,用于标记那些扩大了作用域(包或公共)的方法。我使用@Private注释来做同样的事情。

虽然必须测试公共API,但有时获取通常不是公共的东西是方便和明智的。

当:

通过将一个类分解为多个类,类的可读性会显著降低, 为了让它更容易测试, 并且提供一些对内部的测试访问就可以做到这一点

宗教似乎战胜了工程学。

当您想要测试的某个方法中有复杂的逻辑时,这是一个很好的指标,表明该类违反了单一责任原则。

一个很好的解决方案是:

为原始方法的功能创建一个接口。 在类中实现并测试该接口。 将接口注入到原始类中。

在. net中,有一个叫做PrivateObject的特殊类,专门用于允许您访问类的私有方法。

在MSDN或Stack Overflow上查看更多信息

(我很奇怪,到目前为止还没有人提到它。)

但在某些情况下,这是不够的,在这种情况下,你必须使用反射。

尽管如此,我还是会坚持不测试私有方法的一般建议,然而,像往常一样,总会有例外。