关于java:annotation,使私有方法仅对测试类公开

annotation to make a private method public only for test classes

本问题已经有最佳答案,请猛点这里访问。

谁有解决这个共同需求的办法?

我的申请表上有一门课。

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

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

所以,我在想类似的事情

1
2
3
4
5
6
7
8
9
10
11
public class MyClass {

   public void somePublicMethod() {
    ....
   }

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

上面的注释将私有方法标记为"public for tests"这意味着,编译和运行时将被允许用于测试中的任何类…程序包,而编译和或运行时对于不在测试包中的任何类都将失败。

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

似乎写的单元测试越多,破坏封装的信息就越多…


通常的方法是使私有方法受保护或包私有,并将此方法的单元测试与被测试的类放在同一个包中。guava有一个@VisibleForTesting注释,但它只是用于文档目的。


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

Junit医生说:

测试私有方法可能意味着应该将这些方法移到另一个类中以促进可重用性。但如果你必须…如果您使用的是JDK1.3或更高版本,那么可以使用反射在privilegedaccessor的帮助下破坏访问控制机制。有关如何使用它的详细信息,请阅读本文。


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


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

如果你坚持同时注释你的私有方法,你可以使用谷歌的@visiblefortesting注释。


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


或者您可以将此方法提取到某个策略对象。在这种情况下,您可以很容易地测试提取的类,并且不公开方法,也不使用反射/字节码实现某种魔力。


好吧,这里我们有两个混合的东西。首先,当您需要标记一些只在测试中使用的东西时,我同意@jb nizet,使用guava注释会很好。

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


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

像这样的班级

1
2
3
4
5
public class Outer {
    private static class Inner {
        private int foo() {return 2;}
    }
}

它提供了如下语法:

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

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


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

对此有两种一般方法

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

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

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


我不知道任何这样的注释,但是以下可能是有价值的:单元测试私有方法或以下内容:jmockit


据我所知,没有这样的注释。最好的方法是像其他一些人建议的那样使用反射。看看这篇文章:如何测试具有私有方法、字段或内部类的类?

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

虽然有@publicfortests注释,但这是个好主意。

干杯!


我只是把测试放在类中,使它成为一个内部类:网址:http://www.ninthavenue.com.au/how-to-unit-test-private-methods