测试私有变量 - 总是不良实践吗?

5
为了提供一些背景,我已经学习Java大约10个月了,所以我的经验并不是很丰富。最近我看到一些关于测试私有方法和变量的不良实践的文章。
在理想的情况下,你不应该这么做,因为它意味着设计不良-然而,我正在使用一个旧的框架,在那里大多数方法都是通过反射调用,这是个糟糕的设计,但无论如何我都不能改变它。请不要回复说“你应该重新设计你的代码”,因为我无法改变框架的工作方式。
我想测试一个“流”类是否以特定方式运行,并根据私有变量的状态调用正确的方法,我希望确保某些方法设置私有实例变量的正确值,如果另一个私有变量具有特定值。这样我就可以确保当我对类进行未来更改时,类的流程/行为没有被破坏或改变。
现在,因为流程在很大程度上基于私有实例变量的状态,并且测试私有实例变量的状态是不好的,那么我该如何测试这个类呢?
以下是几种测试私有变量的方法:
  1. 在代码结尾处实现默认访问getter和setter,并将junit测试类放在相同的包中。清晰地注释它们只用于测试。
  2. 将实例变量设为默认访问而不是私有访问,并将junit测试类放在同一个包中。同一包中的其他类也不会实例化这个类。
  3. 通过反射测试私有变量-这里我失去了IDE功能,因为如果我更改变量的名称,Eclipse不会重构,并且可能未来需要手动更改字符串以匹配要测试的类中的变量名。
以上哪种方法是“较小”的恶可以使用?测试私有变量比没有测试好吗?

1
你不应该测试私有变量。测试类的功能,而不是如何实现它。 - Bohemian
选择Bohemian的答案作为最佳答案。我将按照应用程序运行时调用的顺序调用公共方法,然后查看某些方法是否调用其他方法。在我测试的方法之前调用的公共方法应该将私有变量设置为某些会使方法表现不同的内容,我可以测试这种行为。这可能带来的一个缺点是,如果我想在某些流程中添加方法,我必须更新我的测试以反映这一点,并确保它们也调用该方法! - DeaIss
2个回答

8
私有字段的状态与类的正确运行无关。您不应该测试私有变量。
测试类的“做什么”,而不是“如何做”。
如果您想测试类正确设置其内部状态,以便在此之后以特定方式运行,则调用设置状态的方法并测试此后的行为是否正确。
即使需要进行数千次测试来确保这一点-它们仅是单元测试,因此速度很快。
未来的编码人员可以自由更改类的内部工作方式,只要维护类的契约即可。

当我看到这个响应后,我立即看到的一个问题是我的方法会做一些事情,等待用户在HTML页面上点击某些东西,然后方法会再做一些事情,等待用户与某些硬件进行交互,然后方法会再做一些事情等等。有些用户响应无法模拟,因此我唯一能做的就是通过修改私有变量来“模拟”或模仿它们,如果用户以某种方式与硬件或HTML页面进行交互,则这些变量将被更改。 - DeaIss
1
然后,将您的类分解为抽象用户交互,以便您可以模拟它,或者更加努力地模拟它(实际上几乎所有东西都可以被模拟!) - Bohemian
这正是我试图做的...但被告知要恢复到“标准”设计模式!不过,我想我明白你的意思。例如,我可以调用所有在happyday流程中调用的方法(并按照happyday预期的顺序),然后查看最后一个方法(通常会在变量Y设置为true时调用methodX...如果按照happyday流程进行,它应该是这样的)是否确实像我期望的那样调用了methodX。这样我就不必测试或设置任何私有变量。听起来对吗? - DeaIss
是的,这听起来没问题。单个测试需要许多步骤也是可以的。然而,测试所需的许多步骤表明代码可能存在一些设计问题 - 也许类试图做太多事情(内聚性)或存储过多状态等。同样,考虑将类分解为更小的类,每个类都有更紧密/更窄的关注范围,并在更高级别上将它们组合在一起。这样,您可以单独测试每个部分,将几个部分组合在一起进行一些更广泛的单元测试,并让系统测试捕获大局观测试。 - Bohemian

0

第一种选择对您来说是一个不错的选择。 在遵循良好的编码实践时,我们应该始终将变量设置为私有,并使方法公开,以便变量不能被修改,而方法可以被外部访问。


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