如何在Java应用程序中测试私有构造函数?

Jam*_*sev 44 java junit unit-testing

如果一个类包含一堆静态方法,为了确保没有人错误地初始化这个类的实例,我创建了一个私有构造函数:

private Utils() {
}
Run Code Online (Sandbox Code Playgroud)

现在..如果不能看到构造函数,怎么能测试呢?这可以覆盖测试吗?

Boh*_*ian 68

使用反射,您可以调用私有构造函数:

Constructor<Util> c = Utils.class.getDeclaredConstructor();
c.setAccessible(true);
Utils u = c.newInstance(); // Hello sailor
Run Code Online (Sandbox Code Playgroud)

但是,你甚至可以做到这一点:

private Utils() {
    throw new UnsupportedOperationException();
}
Run Code Online (Sandbox Code Playgroud)

通过在构造函数中抛出异常,可以防止所有尝试.


我也会自己上课final,只是"因为":

public final class Utils {
    private Utils() {
        throw new UnsupportedOperationException();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • +1.关于异常的优点! (7认同)
  • 我发现UnsupportedOperationException比IllegalStateException更合适. (3认同)

Mih*_*der 19

测试代码的意图..总是:)

例如:如果构造函数的私有点是不可见的,那么你需要测试的是这个事实,而不是别的.

使用反射API查询构造函数并验证它们是否具有私有属性集.

我会做这样的事情:

@Test()
public void testPrivateConstructors() {
    final Constructor<?>[] constructors = Utils.class.getDeclaredConstructors();
    for (Constructor<?> constructor : constructors) {
        assertTrue(Modifier.isPrivate(constructor.getModifiers()));
    }
}
Run Code Online (Sandbox Code Playgroud)

如果要对对象构造进行适当的测试,则应测试允许您获取构造对象的公共API.这就是所述API应该存在的原因:正确构建对象所以你应该测试它:).


MrS*_*h42 6

@Test
public//
void privateConstructorTest() throws Exception {
    final Constructor<?>[] constructors = Utils.class.getDeclaredConstructors();
    // check that all constructors are 'private':
    for (final Constructor<?> constructor : constructors) {
        Assert.assertTrue(Modifier.isPrivate(constructor.getModifiers()));
    }        
    // call the private constructor:
    constructors[0].setAccessible(true);
    constructors[0].newInstance((Object[]) null);
}
Run Code Online (Sandbox Code Playgroud)

  • @ MrSmith42让测试覆盖率接近100%并不是一件容易的事情.测试覆盖率是一个指标.任何旨在改进度量而不是实现实际结果的行为都会降低度量标准.毕竟,您可以通过执行所有方法的测试覆盖所有代码,但不验证结果.因此,只有在您有充分理由这样做的情况下,通过直接调用私有构造函数来测试私有构造函数才有意义.(如果可能的话,最好间接测试它 - 通过调用工厂方法或类似的东西).无论如何,如果需要知道怎么做是好的:-) (2认同)
  • @Alexey Tigarev:如果我有一个 utils 类,其中从不调用构造函数,并且所有静态方法都经过 100% 测试。测试覆盖了 100% 曾经调用过的方法,所以我喜欢覆盖工具也报告该类的 100% 覆盖率。如果这只能通过以这种方式“测试”从未使用过的私有构造函数来实现,我建议这样做。 (2认同)

Lui*_*ano 5

确保没有人错误地初始化这个类的实例

通常我所做的是将方法/构造函数从私有更改为默认包可见性.我对我的测试类使用相同的包,因此从测试中可以访问方法/构造函数,即使它不是来自外部.

要强制执行策略以不实例化该类,您可以:

  1. 从默认的空构造函数中抛出UnsupportedOperationException("不要实例化此类!").
  2. 声明类抽象:如果它只包含静态方法,则可以调用静态方法但不实例化它,除非您将其子类化.

或者同时应用1 + 2,如果您的测试与目标类共享相同的包,您仍然可以继承并运行构造函数.这应该是非常"错误证明"; 恶意程序员总会找到一个解决方法:)