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

Java 注释使私有方法仅对测试类公开,java,unit-testing,junit,annotations,Java,Unit Testing,Junit,Annotations,世卫组织有解决这一共同需求的办法 我的申请表上有一个等级 有些方法是公共的,因为它们是api的一部分, 有些是私有的,因为它们用于内部使用,以使内部流更具可读性 现在,假设我想编写一个单元测试,或者更像是一个集成测试,它将位于一个不同的包中,允许调用这个方法,但是,如果您试图从应用程序本身的类调用它,我希望不允许对这个方法的正常调用 所以,我在想类似的事情 public class MyClass { public void somePublicMethod() { ....

世卫组织有解决这一共同需求的办法

我的申请表上有一个等级

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

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

所以,我在想类似的事情

public class MyClass {

   public void somePublicMethod() {
    ....
   }

   @PublicForTests
   private void somePrivateMethod() {
    ....
   }
}
上面的注释将私有方法标记为“测试的公共方法” 这意味着,编译和运行时将被允许用于测试中的任何类。。。包,而对于不在测试包下的任何类,编译和\或运行时都将失败

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


似乎编写的单元测试越多,就越有可能破坏封装…

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

我不知道有任何这样的注释,但是以下内容可能很有价值:

或者如下所示:

常用的方法是使私有方法受保护或包私有,并将此方法的单元测试与被测试的类放在同一个包中


Guava有一个,但它仅用于文档目的。

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

您不能这样做,既然这样,您怎么能够编译您的测试呢?编译器不会考虑注释

有两种通用的方法来解决这个问题

第一种方法是使用反射来访问方法

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


当然,如果您进行黑盒测试,那么无论如何都不应该访问私有成员。

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

JUnit文档说:

测试私有方法可能意味着应该将这些方法转移到另一个类中以提高可重用性。 但是如果你必须。。。
如果您使用的是JDK1.3或更高版本,那么可以使用反射在PrivilegedAccessor的帮助下颠覆访问控制机制。有关如何使用此方法的详细信息,请参见,或者您可以将此方法提取到某个策略对象。在这种情况下,您可以轻松地测试提取的类,而不必公开方法或使用反射/字节码进行一些魔术。

据我所知,没有这样的注释。最好的方法是像其他人建议的那样使用反射。请看这篇帖子:

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

尽管有@PublicForTests注释,但这是个好主意

干杯

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


如果您坚持还要注释您的私有方法,您可以使用Google的@VisibleForTesting注释。

我只是将测试放在类本身中,使其成为一个内部类:

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

像这样的班级

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
类。

好的,这里我们有两个混合的东西。首先,当您需要标记一些只在测试中使用的东西时(我同意@JB Nizet),使用番石榴注释会很好


另一件事是测试私有方法。为什么要从外部测试私有方法?我是说。。您应该能够通过对象的公共方法测试对象,并在测试结束时测试其行为。至少,我们正在做并试图教给初级开发人员,他们总是尝试测试私有方法(作为一种良好实践)

为什么不使用反射来访问私有方法?@Scott在宣传自己的节目时,“你必须在回答中披露你的从属关系。”()。不质疑流形框架本身,只是你提升它的微妙方式。如果你使用FindBugs,我为你构建了
@VisibleForTesting
方法不会在测试类之外使用。我的类不可能全部在测试类中