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



对于私有方法测试的意义有不同的看法,例如这里和这里。我个人认为这是有道理的,问题是如何正确地做。在c++中,您可以使用#define hack或使测试类friend,在c#中有InternalsVisibleToAttribute,但在Java中,我们要么使用反射,要么使它们"测试可见",并注释它们,以便使意图清晰。两者的缺点应该是相当清楚的。

我认为应该有更好的。从

public class Something {
    private int internalSecret() {
        return 43;
    }
}
如果能在测试代码中调用私有方法就好了,比如
@MakeVisibleForTesting Something something = new Something();
Assert.assertEquals(43, something.internalSecret());

这里的注释将使用反射将所有调用静默地转换为something的私有方法。我想知道Lombok是否可以做到这一点(我将询问作者)。

很有可能做这么多魔术太复杂了,而且在任何情况下都需要一些时间,所以我正在寻找一些替代方法。也许用@Decapsulate之类的东西注释被测类,并使用注释处理器生成一个类Decapsulated_Something,看起来像

public class Decapsulated_Something {
    public Decapsulated_Something(Something delegate) {
        this.delegate = delegate
    }
    public boolean internalSecret() {
        // call "delegate.internalSecret()" using reflection
    }
    ...
}

允许使用

Decapsulated_Something something = new Decapsulated_Something(new Something());
Assert.assertEquals(43, something.internalSecret());

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

  • 这个实现起来有多复杂?
  • 我忘记了什么?
  • 你对它的总体看法如何?

这个实现看起来很麻烦。这可能不值得。而只是将方法包设为默认值。

然而,如果你决定调用私有方法,你可以在Decapsulated_something类中使用setAccessible来允许通过反射调用。这很简单

如果能在测试代码中调用私有方法就好了,比如
@MakeVisibleForTesting Something something = new Something();
Assert.assertEquals(43, something.internalSecret());

有这样一个方法注释,检查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] 
    }

有很多方法可以使用

  • 不要测试私有方法,因为它们是隐藏的实现细节,不会对调用者产生影响。
  • 使方法包本地,这样调用者不能访问它们,但你可以在同一个包中访问它们,即单元测试。使单元测试成为一个内部类或提供一个包本地内部类。不确定这是一个改进!
  • 使用反射访问类的方法。这就像把一个方法标记为私有的,而不是私有的,这是一种混乱。只有当一个方法是真正私有的时候,你才应该把它标记为私有。

我将回答"一般"问题:-)只需要几行代码就可以通过反射访问方法,并且有相当多的库,utils, api等提供了这样做的方法。您可能还可以在自己的代码中使用许多不同的技术。例如字节码操作、反射、类扩展等。但我更倾向于把事情简单化。虽然测试私有方法很有用,但您也可能只想测试几个方法。所以设计一些复杂的东西可能是多余的。我只会使用一个已建立的API,或者编写一个快速方法来访问我感兴趣的私有方法,然后让它完成。

几年前我从事过一个项目,该项目生成了一些类,以便更容易地对私有方法进行单元测试。http://java.net/projects/privateer/

它生成了额外的类,使它比调用反射更容易,例如,如果你有MyClass.myPrivateMethod(),它将生成一个_MyClass类,允许直接调用myPrivateMethod。

它从来没有真正完成,在一些情况下是有用的,但总的来说,我不建议测试私有方法,除非绝对必要。通常,将它们重新设计为实用程序类(如果担心用户使用它们,可以使用包访问)是一个更好的选择。

相关内容

  • 没有找到相关文章

最新更新