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


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

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

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

更新

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

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


当前回答

一些很棒的答案。我没有看到提到的一件事是,在测试驱动开发(TDD)中,私有方法是在重构阶段创建的(关于重构模式的示例,请参阅Extract Method),因此应该已经具有必要的测试覆盖率。如果做得正确(当然,当涉及到正确性时,您将得到各种各样的意见),您应该不必担心必须将私有方法设为公共,以便您可以测试它。

其他回答

在我看来,在编写测试时,你不应该对你的类内部是如何实现的做深入的假设。您可能希望稍后使用另一个内部模型对其进行重构,但仍然保证与以前的实现相同。

记住这一点,我建议你把重点放在测试你的契约仍然存在,不管你的类目前有什么内部实现。基于属性的公共api测试。

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

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

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

单元测试的目的是确认该单元的公共api的工作情况。应该没有必要让一个私有方法只用于测试,如果是这样,那么你的接口应该重新考虑。私有方法可以被认为是公共接口的“助手”方法,因此通过公共接口进行测试,因为它们将调用私有方法。

我认为你有这样做的“需要”的唯一原因是你的类并不是为测试而设计的。

正如其他人所说,单元测试私有方法有点可疑;单元测试公共接口,而不是私有实现细节。

也就是说,当我想对c#中私有的东西进行单元测试时,我使用的技术是将可访问性保护从私有降级为内部,然后使用InternalsVisibleTo将单元测试程序集标记为友程序集。然后,单元测试程序集将被允许将内部组件视为公共的,但您不必担心会意外地增加公共表面区域。

如果你正在使用c#,你可以让方法是内部的。这样就不会污染公共API。

然后将属性添加到dll

[组装:InternalsVisibleTo(“MyTestAssembly”)]

现在所有的方法都在MyTestAssembly项目中可见。也许不完美,但总比为了测试而将私有方法设为公共要好。