注释使私有方法仅对测试类公开

时间:2011-08-02 14:02:40

标签: java unit-testing junit annotations

谁有针对这一共同需求的解决方案。

我的申请表中有一堂课。

某些方法是公开的,因为它们是api的一部分, 有些是私有的,因为内部使用它们使内部流程更具可读性

现在,说我想写一个单元测试,或者更像是一个集成测试,它将位于一个不同的包中,允许调用这个方法,但是,我想要正常调用这个方法将如果你试图从应用程序本身的类中调用它,则不被允许

所以,我在考虑那样的事情

public class MyClass {

   public void somePublicMethod() {
    ....
   }

   @PublicForTests
   private void somePrivateMethod() {
    ....
   }
}

上面的注释将私有方法标记为“公共测试” 这意味着,对于在test ...包下的任何类,允许编译和运行时,而对于不在测试包下的任何类,编译和\或运行时将失败。

任何想法? 有这样的注释吗? 有更好的方法吗?

似乎您编写的单元测试越多,您的更多信息就会破坏您的封装......

12 个答案:

答案 0 :(得分:111)

常见的方法是使私有方法受保护或包私有,并将此方法的单元测试放在与被测试类相同的包中。番石榴有@VisibleForTesting annotation,但它仅用于文档目的。

答案 1 :(得分:19)

如果您的测试覆盖率对测试类中的所有公共方法都有效,那么公共调用的私有方法将自动进行测试,因为您将断言所有可能的情况。

JUnit Doc说:

测试私有方法可能表明这些方法应该移动到另一个类中以提高可重用性。 但如果你必须...... 如果您使用的是JDK 1.3或更高版本,则可以使用反射在PrivilegedAccessor的帮助下破坏访问控制机制。有关如何使用它的详细信息,请read this article.

答案 2 :(得分:10)

考虑使用接口来公开API方法,使用工厂或DI来发布对象,以便消费者仅通过接口了解它们。该界面描述了已发布的API。这样你就可以在实现对象上做任何你想要的公开,并且它们的使用者只能看到通过接口公开的那些方法。

答案 3 :(得分:5)

dp4j有你需要的东西。基本上你所要做的就是将dp4j添加到你的类路径中,每当使用@Test(JUnit的注释)注释的方法调用一个私有的方法时它将起作用(dp4j将在编译时注入所需的反射)。您也可以使用dp4j的@TestPrivates注释更明确。

如果你坚持也注释你的私人方法,你可以使用谷歌的@VisibleForTesting注释。

答案 4 :(得分:3)

关于Testing Private Methods的文章列出了一些测试私有代码的方法。使用反射会给程序员带来额外的负担,以便记住如果重构完成,字符串不会自动更改,但我认为这是最干净的方法。

答案 5 :(得分:2)

或者您可以将此方法提取到某些策略对象。在这种情况下,您可以轻松地测试提取的类,并且不要使用反射/字节码使方法成为公共或魔法。

答案 6 :(得分:1)

我不知道任何此类注释,但以下内容可能具有价值:unit testing private methods
或以下:JMockit

答案 7 :(得分:1)

你不能这样做,从那以后你怎么能编译你的测试?编译器不会考虑注释。

这有两种一般方法

首先是使用反射来访问方法

第二种是使用package-private而不是private,然后将测试放在同一个包中(但在不同的模块中)。它们基本上对其他代码是私有的,但您的测试仍然可以访问它们。

当然,如果你进行黑盒测试,你不应该访问私人成员。

答案 8 :(得分:1)

我们最近发布了一个库,通过反射帮助很多人访问私有字段,方法和内部类:BoundBox

对于像

这样的课程
public class Outer {
    private static class Inner {
        private int foo() {return 2;}
    }
}

它提供了如下语法:

Outer outer = new Outer();
Object inner = BoundBoxOfOuter.boundBox_new_Inner();
new BoundBoxOfOuter.BoundBoxOfInner(inner).foo();

创建BoundBox类唯一需要做的就是编写@BoundBox(boundClass=Outer.class),并立即生成BoundBoxOfOuter类。

答案 9 :(得分:1)

好的,所以我们有两件事情在混合。首先,当你需要标记仅用于测试的东西时,我同意@JB Nizet,使用番石榴注释会很好。

另一件事是测试私有方法。为什么要从外面测试私有方法?我的意思是..你应该能够通过他们的公共方法测试对象,最后是它的行为。至少,我们正在做并尝试向初级开发人员讲授,总是尝试测试私有方法(作为一种好的做法)。

答案 10 :(得分:0)

据我所知,没有这样的注释。最好的方法是使用反射作为其他人建议的。看看这篇文章:
How do I test a class that has private methods, fields or inner classes?

您应该注意测试方法的异常结果。例如:如果你期望IllegalArgumentException,而是你将得到“null”(Class:java.lang.reflect.InvocationTargetException)。
我的一个colegue建议在这些情况下使用powermock framework,但我还没有测试它,所以不知道它究竟能做什么。虽然我已经使用了它所基于的Mockito框架,这也是一个很好的框架(但我认为并不能解决私有方法异常问题)。

虽然拥有@PublicForTests注释,但这是一个好主意。

干杯!

答案 11 :(得分:-1)

我只是将测试放在类本身中,使其成为内部类: http://www.ninthavenue.com.au/how-to-unit-test-private-methods

相关问题