我想测试一个私有方法 – 我的设计有问题吗?
所以我对软件测试非常陌生,我正在考虑为我的一个应用程序添加几个测试。 我有一个公共方法addKeywords(),它沿途调用私有方法removeInvalidOperations()。 这种私有方法调用外部API并且是大约50行代码。 我认为这是一个有点复杂的方法,我想通过调用addKeyword()方法来测试它,而不必这样做。 但这似乎不可能(至少不是JUnit)。
我所看到的信息表明,测试私有方法的愿望可能是代码味道。 有些人认为这可能表明这应该被重构为一个单独的类并公之于众。 此外,还有一些建议是,如果您确实需要,则可以对生产代码进行编辑,例如更改私有方法的可见性。
我真的不明白为什么我当前的代码设计有问题,但也不喜欢编辑我的生产代码以满足我的测试需求的想法。
正如我所说 – 我对测试很新,所以任何帮助都非常感谢。 另外,如果有任何进一步的信息,我可以告诉我,以帮助解答。
我建议重构一下。
我所看到的信息表明,测试私有方法的愿望可能是代码味道。 有些人认为这可能表明这应该被重构为一个单独的类并公之于众。
你已经在自己的问题中涵盖了支持和反对它的各种原因,你似乎很清楚这些论点。 但是你有一个看似相当复杂的方法并且涉及一个外部API。 这值得自己测试。 removeInvalidOperations()
仍然可以是它所在类的私有方法,但它基本上会委托给另一个依赖项。
class YourClass { private OperationRemover remover; public void addKeywords() { // whatever removeInvalidOperations(); } private void removeInvalidOperations() { remover.remove(); } }
这为您提供了在某些时候能够替换此依赖项的额外好处,包括能够在不实际放置外部API调用的情况下测试您的addKeywords()
方法,这将使测试该方法更容易。 例如, OperationRemover
可以是一个接口,出于测试目的,您只需传入一个存根而不是生产中使用的具体版本。 至于具体版本,您可以独立于现有类的内容编写测试。
我真的不明白为什么我当前的代码设计有问题,但也不喜欢编辑我的生产代码以满足我的测试需求的想法。
更易于测试是一项附带好处。 再看看它:你实际做的是使代码松散耦合和可扩展。 上面,我们将调用外部API与可能需要使用结果的代码分开。 外部API可能会发生变化。 您可能会从一个服务转到另一个服务,但使用该结果的代码不必关心。 该类可以保持不变,只有实际调用的类需要修改(或替换)。
现实世界的例子:这一年是2007年,你在美国一家大型金融中心的银行工作。 您的应用程序需要使用帐户信息。 您的代码可以访问银行内部的某种Web服务,并以所需的forms获取所需的信息,然后继续处理它。 2008年,美国金融业崩溃,你的银行(处于崩溃边缘)被另一家银行吞并。 您的应用程序可以免除,除非您现在必须联系到尚存的银行中已存在的其他API以从中获取帐户信息。 消费此帐户信息的代码是否需要更改? 不必要。 它与以前的帐户信息相同,只是来自不同的来源。 不,所有需要改变的是调用API的实现。 消费代码永远不必知道。
这种松散耦合也促进和促进测试的事实是一个奖励。
如果它是private
,它不能被视为应用程序API的一部分,所以测试它确实是代码味道 – 当测试中断时,是否可以?
unit testing应该是面向function的 ,而不是面向代码的 。 您测试function单元,而不是代码单元。
无论哲学如何,实现之外的类都无法在不破坏JVM的情况下访问私有方法,因此您运气不好 – 您必须更改方法的可见性,使unit testing类扩展的protected
测试API,或者通过调用使用它的公共方法间接测试函数。
通常您不想测试私有方法,但也有例外。
如果出现以下情况,您可能会尝试测试私有方法:
-
您没有仔细考虑如何通过调用现有的公共方法间接测试私有方法。
-
你class级的API太不灵活了。 公共方法需要更多参数,或者某些私有方法需要公开。
-
你的类的API足够灵活,但在公共方法下面,它有一些相当复杂的私有方法。
根据您的问题,您可能处于任何一种情况。
对于(1),显然你应该首先尝试使用现有的公共方法来测试私有方法。
对于(2)和(3),unit testing不会告诉你你处于哪种情况。你需要做的是编写一些示例代码。 正如Josh Bloch建议的那样 ,为您的API编写一些用例。 您的API应该是满足您的用例所需的最小公共方法集。
(3)是可以测试私有方法的情况。 有各种各样的技巧 。 对于生产代码,这些比将方法暴露给API用户(公开)更好,这样您就可以测试它。 或者将相关function拆分为2个类,以便您可以对其进行测试。
你可以从信息隐藏的角度思考,而不是用“代码气味”来思考,这是不精确和主观的。 不应在您的公共API中公开可能更改的设计决策。 优选地,可能改变的设计决策也不应暴露于您的unit testing – 这就是人们建议不要测试私有方法的原因。
但是如果你真的认为对你的私有方法进行unit testing是很重要的,如果你不能通过公共方法充分地做到这一点,那么就不要牺牲代码的正确性! 测试私有方法。 最糟糕的情况是您的测试代码更加混乱,并且您必须在私有方法更改时重写测试。
如果你不想调用addKeywords()
,也许你应该只添加另一个公共方法testRemoveInvalidOperations()
, testRemoveInvalidOperations()
调用私有的removeInvalidOperations()
。 您可以在以后删除测试。
- 使用Java的Pdf页数
- 如何强制JSON-lib的JSONObject.put(..)转义包含JSON的字符串?
- 创建Web服务客户端时,没有主题备用名称存在exception
- Websocket:在页面重新加载后维护用户会话
- ClassCastException:java.math.BigInteger在连接MySQL时无法强制转换为java.lang.Long
- 如何使用java中的XMLEndcoder在xml文件中编写带有数据的JTable状态
- 如何将jndi查找从xml转换为java配置
- 我不知道如何从我的文本字段中获取数据
- 如何使用Java HttpServer / HttpExchange在GET中获取查询字符串?