关于java:我应该对私有方法进行单元测试吗?

Should I unit test private methods?

我知道在这些网站上有很多帖子[1,2]正在讨论是否应该直接或间接地测试私人方法。
我似乎无法理解的是,我如何测试它所在的类 - 例如 -
3个私有方法,由10种不同的公共方法接近。

假设私有方法对其特定的数据结构进行排序,或者以一种只与该类相关的特殊方式从它们中检索一个值(我不打算在每个场景中创建一个内部类)。

现在,如果我选择间接测试私有,那么每次我测试公共方法时都必须重新编写私有逻辑的测试,以便完全测试方法并使单元测试保持独立。
(并不总是可以在测试相互代码的测试类中创建私有方法)
我将要写一个重复代码和长测试方法。

那么间接测试如何作为标准?


在我看来,促进你的类及其方法的低耦合和高内聚是迄今为止TDD最重要的贡献(比"验证代码按预期工作"更重要)。

在你强迫自己对每种方法(或多或少)进行单元测试之前,这一点并不明显。只需使私有方法包可见(在这种情况下打破封装是合理的)。

例如,您很快就会发现,测试接受参数并返回某些内容的方法更容易,而不依赖于(或影响)类状态。显然情况并非如此,但是如果将问题分解得足够多,您将拥有更多可测试(且更易读)的代码。

当设计与类状态紧密耦合并且不能解耦时,模拟框架可以节省生命(这是可行的并且发生在所有命令式语言上)。例如,您可以在运行测试之前用模拟实例替换(再次打包 - 可见)字段的值。确保验证模拟上的调用!间谍活动也是合理的,但我个人更喜欢将其作为最后的手段。

总之,可能。换句话说,如果编写测试很难,请考虑重构代码;)


我同意您链接的主题中的答案中的用户eis(请参阅上面的评论):

the real answer is that if you have the urge to test a private method, the method shouldn't be private; if making the method public bothers you, chances are, it is because it is part of a separate reponsibility; it should be on another class.

尽量避免测试私有方法。它们应该只使代码更具可读性。如果私有方法变得如此复杂以至于应该进行单元测试,请将其提取到一个新类中,然后您可以正确/轻松地进行单元测试。


私有方法是一个实现细节。您的测试应侧重于:

  • 方法的外部可见行为
  • 您的类与其依赖项的交互

您应该通过以下两种策略之一验证所有功能。

这基本上分解为第一点:

  • 如果我使用参数yz调用方法x,那么它应该返回a
  • 如果我使用参数yz调用方法x,那么当我读取属性a时,它应该具有值b

或者这是第二次

  • 如果我使用参数yz调用方法x,那么它应该使用参数y+z调用dependency a

如果您的测试属于这种风格,那么更改内部实现将对测试没有影响(即,测试不会很脆弱),除非更改是改变类与其依赖项交互的方式,在这种情况下您的测试将具有无论如何要改变。

你没有理由需要测试类的内部因为它是否从外部看不到它的内部结构(直接通过读取属性,或通过调用具有某些特定参数的另一个方法并查看结果来间接看到它的内部结构)如果该方法调用受到先前创建的内部状态的影响,或者它与其依赖关系的交互,则它是无关紧要的。

鉴于您的具体示例,听起来您在游戏中有不同的职责。你有一些类负责进行排序(一个Sorter?),它应该是你的主类的依赖。然后,您可以单独测试排序类以验证它是否符合您的预期(上面的类型1测试),然后在此类上使用类型2测试,以确保类调用Sorter您提供它以确保元素正确排序。

以这种方式将事物分开不仅可以提供可测试性,还意味着您有可能在其他地方重用分拣机。