首页 文章

注释使私有方法仅对测试类公开[复制]

提问于
浏览
72

这个问题在这里已有答案:

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

我的应用程序中有一个类 .

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

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

所以,我在想这样的事情

public class MyClass {

   public void somePublicMethod() {
    ....
   }

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

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

有什么想法吗?有这样的注释吗?有一个更好的方法吗?

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

12 回答

  • 4

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

  • 2

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

  • 1

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

  • 0

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

    JUnit Doc说:

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

  • 0

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

  • 10

    dp4j有你需要的 . 基本上你所要做的就是将dp4j添加到你的类路径中,每当一个方法用@Test注释时(JUnit 's annotation) calls a method that'私有它将起作用(dp4j将在编译时注入所需的反射) . 你也可以使用dp4j的@TestPrivates注释来更明确 .

    如果您坚持也注释您的私人方法,您可以使用Google的@VisibleForTesting注释 .

  • 1

    我不知道任何这样的注释,但以下可能是有 Value 的:unit testing private methods
    或以下:JMockit

  • 108

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

    有两种一般方法

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

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

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

  • 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 类 .

  • 3

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

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

  • 18

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

    您应该注意测试方法的异常结果 . 例如:如果你期望IllegalArgumentException,而是你得到"null"(Class:java.lang.reflect.InvocationTargetException) .
    我的一个colegue建议在这些情况下使用powermock framework,但我没有解决私有方法异常问题 .

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

    干杯!

  • 1

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

相关问题