用于测试私有方法的Java工具?

maa*_*nus 7 java testing reflection private

关于私有方法测试的意义有不同的意见,例如,这里这里.我个人认为这是有道理的,问题是如何正确地做到这一点.在C++中你可以使用#definehack或者使用测试类friend,在C#中有InternalsVisibleToAttribute,但是在Java中我们必须使用反射或使它们"可见以进行测试"并对其进行注释以使意图清晰.两者的缺点应该非常清楚.

我认为应该有更好的东西.从...开始

public class Something {
    private int internalSecret() {
        return 43;
    }
}
Run Code Online (Sandbox Code Playgroud)

能够在测试代码中调用私有方法会很好

@MakeVisibleForTesting Something something = new Something();
Assert.assertEquals(43, something.internalSecret());
Run Code Online (Sandbox Code Playgroud)

这里的注释会静默地将所有调用转换为something使用反射的私有方法.我想知道龙目岛是否可以做到(并会问作者).

做这么多魔术很可能证明太复杂了,无论如何它都需要一些时间,所以我正在寻找一些替代方案.也许用类似的东西@Decapsulate来注释正在测试的类,并使用注释处理器来生成Decapsulated_Something类似的类

public class Decapsulated_Something {
    public Decapsulated_Something(Something delegate) {
        this.delegate = delegate
    }
    public boolean internalSecret() {
        // call "delegate.internalSecret()" using reflection
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

这将允许使用

Decapsulated_Something something = new Decapsulated_Something(new Something());
Assert.assertEquals(43, something.internalSecret());
Run Code Online (Sandbox Code Playgroud)

我对注释处理没有多少经验,所以我先问一下:

  • 这有多复杂?
  • 我忘记了什么?
  • 你对此有何看法?

Ale*_*man 7

执行此实现似乎很麻烦.它可能不值得.而只是使方法包默认.

但是,如果您决定调用私有方法,则可以在类中使用setAccessibleDecapsulated_something以允许通过反射进行调用.所以这很简单.


sim*_*ico 2

如果能够在测试代码中调用私有方法就好了,比如

@MakeVisibleForTesting Something something = new Something();
Assert.assertEquals(43, something.internalSecret());
Run Code Online (Sandbox Code Playgroud)

有一个方法注释之类的东西,查看dp4j@TestPrivates

@Test
@TestPrivates 
//since the method is annotated with JUnit's @Test this annotation is redundant. 
// You just need to have dp4j on the classpath.
    public void somethingTest(){
      Something something = new Something();
      int sthSecret = something.internalSecret();
       Assert.assertEquals(43, sthSecret); //cannot use something.internalSecret() directly because of bug [dp4j-13][2] 
    }
Run Code Online (Sandbox Code Playgroud)