在Java中对私有和静态方法进行单元测试

3
我正在为我的一个应用程序编写单元测试,作为良好的实践,我尽可能使类中的所有方法都私有化,因此我可能会得到大多数是私有方法、几个公共方法和有时调用一些静态方法的类(无论是我的其他类还是TextUtils等)。
我想知道如何通过仅依赖Mockito和JUnit来测试所有类,因为Robolectric和Powermockito似乎超越了单元测试应该做的事情。我应该忽略所有私有和静态方法以及偶然调用一些静态或私有方法的公共方法吗?或者怎么办?

2
这是两个非常不同的问题。通常,私有成员应该通过公共接口间接测试,而静态方法通常可以独立测试。 - chrylis -cautiouslyoptimistic-
2个回答

3
注意:由于您的问题没有提供需要评论的代码,因此以下是一些一般信息。
由于私有方法通常无法在类外部访问(但反射是另一回事),且通常用于为公共方法和受保护的方法提供功能,因此您的单元测试只需测试公共和受保护的方法。如果您仔细选择测试数据,应该能够执行大多数/全部代码。
您可以使用Mockito模拟出测试类所需的任何依赖关系。您可以使用期望(Mockito.when(...).thenReturn(...)或Mockito.verify(mockedClass).method(...))来模拟外部功能或检查被测试类是否按预期进行了传出调用。
您可以使用断言来检查正在测试的方法返回适当的值。
请记住,具有高代码覆盖率的详细单元测试第一次尝试更改测试类的内部实现时可能会出现故障。这是一个平衡行为,您需要找到合适的覆盖范围,同时最小化测试的脆弱性。

谢谢您的回答,我在上面的评论中解释了为什么我认为跳过直接私有方法测试可能是错误的。 - kioli

3

你正在测试的类中的所有私有方法都应该由某个公共/受保护/包私有方法调用;否则它们是未使用的代码。因此,只需专注于测试这个对你的应用程序的“客户端代码”可见的公共API即可。私有方法的内部将作为副作用被测试/覆盖,因为它们实际上实现了API指定的公共合同。

直接测试实现细节(私有方法)会使测试更难以维护,而待测试的代码更难以重构。


谢谢你的回答。我其实也想到了这个,但是在我的脑海中听起来有些不对劲,因为如果我有一个公共方法,它还调用一个私有方法,而我测试前者以捕捉它们两个,感觉我不再测试一个“单元”,而是一个“整体”。 - kioli
1
“单元”在单元测试中并不总是那么容易定义。但总的来说,如果你专注于测试类的公共接口并保持实现细节的封装,长远来看会使事情变得更容易。如果您觉得私有方法正在执行您想要特别测试的操作,那么这可能意味着该逻辑应该建模为自己的类,然后可以(公开地)单独进行单元测试。 - Mick Mnemonic
@kioli:“感觉我现在测试的不再是一个'单元',而是一个'集合体'。”- 这里的问题是什么是一个“单元”?我喜欢Roy Osherove的定义:“一个单元是一堆代码,它们有相同的变更原因。”这意味着一个单元可以是一个单独的方法或几个类。 - Timothy Truckle
非常感谢,我会尝试将这种方法应用于我已经准备好的所有测试中。 - kioli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接