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


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

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

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

更新

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

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


当前回答

在java中,还可以选择将其包设置为private(即去掉可见性修饰符)。如果您的单元测试与被测试的类在同一个包中,那么它应该能够看到这些方法,并且比将方法完全公开要安全一些。

其他回答

我通常将测试类保持在与测试类相同的项目/程序集中。 这样,我只需要内部可见性来使函数/类可测试。

这在一定程度上使您的构建过程变得复杂,需要过滤掉测试类。 我通过将所有测试类命名为TestedClassTest并使用正则表达式筛选这些类来实现这一点。

当然,这只适用于你的问题中的c# / .NET部分

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

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

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

不,因为有更好的方法来剥猫皮。

一些单元测试利用依赖于类定义中的宏,当在测试模式中构建时,这些宏会自动扩展以创建钩子。很有C风格,但是很好用。

一个更简单的OO习惯用法是使您想测试的任何东西都是“受保护的”,而不是“私有的”。测试工具继承自被测试类,然后可以访问所有受保护的成员。

或者你选择“朋友”。就我个人而言,这是我最不喜欢的c++特性,因为它打破了封装规则,但它恰好是c++实现某些特性所必需的。

无论如何,如果您正在进行单元测试,那么您很可能需要向这些成员中注入值。白盒短信是完全有效的。这真的会破坏您的封装。

最近,当重构一个大方法(> 200行)时,我也有同样的想法。对于每个逻辑步骤,我成功地将大方法拆分为较小的方法,因此很容易进行推理。

当涉及到重构出来的小型私有方法时,我想知道我是否应该单独测试它们,因为如果我只测试公共方法,我仍然在测试大方法,测试根本没有从重构中受益

经过一番思考,我意识到:

if all the small methods are private and can't be reused by others, maybe I am doing something wrong: I am not pulling the right abstraction from the code, I am only splitting the big methods treating them like lines/strings, not like mental barrier when I came to the right small methods(I refactored again, completely changing the small methods), and move the small methods into another class exposed as public methods for others to use, now I can test them(and I should test them, they will be used more and deserver the attention)

简介:

我仍然有很多小的私有方法,但是它们共享了很多公共方法,而且小方法真的很小(3-4行,主要是函数调用),但我不会测试它们,我只需要在另一个类中测试共享的公共方法

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

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