I want to test a private method - is there something wrong with my design?
所以我对软件测试非常陌生,我正在考虑为我的一个应用程序添加几个测试。我有一个公共方法addKeywords(),它沿途调用私有方法removeInvalidOperations()。这种私有方法调用外部API,并且有大约50行代码。我认为这是一个有点复杂的方法,我想通过调用addKeyword()方法来测试它,而不必这样做。然而,这似乎不可能(至少不是JUnit)。
我所看到的信息表明,测试私有方法的愿望可能是代码味道。有些人认为这可能表明这应该被重构为一个单独的类并公之于众。此外,还有一些建议,如果您确实需要,则可以对您的生产代码进行编辑,例如:更改私有方法的可见性。
我真的不明白为什么我当前的代码设计有问题,但也不喜欢编辑我的生产代码以满足我的测试需求的想法。
正如我所说 - 我对测试很新,所以任何帮助都非常感激。此外,如果有任何进一步的信息,我可以告诉我,以帮助解答。
我建议重构一下。
The information I have looked at is suggesting that the desire to test
ones private methods could be a code smell. Some people suggest that
it may be a sign that this should be refactored into a separate class
and made public.
你已经在自己的问题中涵盖了支持和反对它的各种原因,你似乎很清楚这些论点。但是你有一个看似相当复杂的方法,并涉及一个外部API。这值得自己测试。
1 2 3 4 5 6 7 8 9 10 11 12 13 | class YourClass { private OperationRemover remover; public void addKeywords() { // whatever removeInvalidOperations(); } private void removeInvalidOperations() { remover.remove(); } } |
这为您提供了在某些时候能够替换此依赖项的额外好处,包括能够在不实际放置外部API调用的情况下测试
I don't really see why I have a problem with my current code design,
but also don't like the idea of editing my production code to suit my
tests needs.
更易于测试是一项附带好处。再看看它:你实际做的是使代码松散耦合和可扩展。上面,我们将调用外部API与可能需要使用结果的代码分开。外部API可能会发生变化。您可能从一个服务转到另一个服务,但使用该结果的代码不必关心。该类可以保持不变,只有实际调用的类需要修改(或替换)。
现实世界的例子:这一年是2007年,你在美国一家大型金融中心的银行工作。您的应用程序需要使用帐户信息。您的代码可以访问银行内部的某种Web服务,并以所需的形式获取所需的信息,然后继续处理它。 2008年,美国金融业崩溃,你的银行(即将崩溃的边缘)被另一家银行吞并。您的应用程序可以免除,除非您现在必须使用已存在的银行中已存在的其他API来从中获取帐户信息。消费此帐户信息的代码是否需要更改?不必要。它与以前的帐户信息相同,只是来自不同的来源。不,所有需要改变的是调用API的实现。消费代码永远不必知道。
这种松散耦合也促进和促进测试的事实是一个奖励。
如果是
单元测试应该是面向功能的,而不是面向代码的。您测试功能单元,而不是代码单元。
无论哲学如何,实现之外的类都不能在不破坏JVM的情况下访问私有方法,所以你运气不好 - 要么必须改变方法的可见性,要么单元测试类扩展
通常您不想测试私有方法,但也有例外。
如果出现以下情况,您可能会尝试测试私有方法:
您没有仔细考虑过如何测试私有方法
通过调用现有的公共方法间接地。
你班级的API太不灵活了。公共方法需要更多
参数或某些私有方法需要公开。
你班级的API足够灵活,但在公众面前
它有一些相当复杂的私有方法
下。
根据您的问题,您可能处于任何一种情况。
对于(1),显然你应该首先尝试使用现有的公共方法来测试私有方法。
对于(2)和(3),单元测试不会告诉你你处于哪种情况。你需要做的是编写一些示例代码。正如Josh Bloch建议的那样,为您的API编写一些用例。您的API应该是满足您的用例所需的最小公共方法集。
(3)是可以测试私有方法的情况。有各种各样的技巧。对于生产代码,这些比将方法暴露给API用户(使其公开)更好,因此您可以对其进行测试。或者将相关功能拆分为2个类,以便您可以对其进行测试。
你可以用信息隐藏来思考,而不是用"代码气味"来思考,这是不精确和主观的。不应在您的公共API中公开可能更改的设计决策。优选地,可能改变的设计决策也不应暴露于您的单元测试 - 这就是人们建议不要测试私有方法的原因。
但是如果你真的认为对你的私有方法进行单元测试是很重要的,如果你不能通过公共方法充分地做到这一点,那么就不要牺牲代码的正确性!测试私有方法。最糟糕的情况是您的测试代码更加混乱,并且您必须在私有方法更改时重写测试。
如果您不想调用