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


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

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

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

更新

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

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


当前回答

我想说这是一个坏主意,因为我不确定你是否会得到任何好处,并可能出现问题。如果你改变一个调用的契约,只是为了测试一个私有方法,你并不是在测试这个类将如何使用它,而是在创建一个你从未打算发生的人为场景。

此外,通过将方法声明为公共,在六个月的时间内(在忘记将方法公开的唯一原因是为了测试之后),您(或者如果您已经移交了项目)完全不同的人将不会使用它,从而导致潜在的意想不到的后果和/或维护噩梦。

其他回答

就我个人而言,我宁愿使用公共API进行单元测试,我当然不会为了方便测试而将私有方法设为公共。

如果您真的想单独测试私有方法,那么在Java中可以使用Easymock / Powermock来实现这一点。

你必须务实,你也应该意识到为什么事情很难测试的原因。

“倾听测试”——如果测试很困难,这是否能告诉你关于你的设计的一些东西?你能不能重构到这样一个地方,对这个方法的测试将是微不足道的,并且很容易通过公共api进行测试?

以下是Michael Feathers在《有效使用遗留代码》一书中所说的话

“很多人花了很多时间试图弄清楚如何解决这个问题……真正的答案是,如果你想测试一个私有方法,这个方法不应该是私有的;如果公开方法让您感到困扰,很可能是因为它是单独责任的一部分;它应该上另一门课。”[有效地使用遗留代码(2005),作者:M. Feathers]

我通常将这些方法保留为受保护的,并将单元测试放在相同的包中(但在另一个项目或源文件夹中),在那里它们可以访问所有受保护的方法,因为类装入器将把它们放在相同的名称空间中。

私有方法通常用作“助手”方法。因此,它们只返回基本值,从不操作对象的特定实例。

如果您想测试它们,您有几个选项。

使用反射 给这些方法包访问权

或者,如果helper方法是一个足够好的新类候选,您可以使用它作为公共方法创建一个新类。

这里有一篇很好的文章。

把它包成私有的怎么样?然后您的测试代码可以看到它(以及包中的其他类),但它仍然对用户隐藏。

但实际上,您不应该测试私有方法。这些是实施细节,不是合同的一部分。它们所做的所有事情都应该通过调用公共方法来覆盖(如果它们的代码不是由公共方法执行的,那么应该去掉)。如果私有代码太复杂,类可能做了太多的事情,需要重构。

公开一个方法是一个很大的承诺。一旦你这样做了,人们就能使用它,你不能再改变他们了。

这都是实用主义。你的单元测试在某种程度上是代码的客户端,为了达到良好的代码覆盖率,你需要让你的代码非常可测试。如果为了让您能够在代码中没有有效的公共接缝的情况下设置必要的极端情况,测试代码非常复杂,那么您的解决方案将是潜在的失败。使用IoC也有助于解决这个问题。