Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Java应用程序中测试私有构造函数?_Java_Unit Testing_Junit - Fatal编程技术网

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

如何在Java应用程序中测试私有构造函数?,java,unit-testing,junit,Java,Unit Testing,Junit,如果一个类包含一组静态方法,为了确保没有人错误地初始化该类的实例,我创建了一个私有构造函数: private Utils() { } Constructor<Util> c = Utils.class.getDeclaredConstructor(); c.setAccessible(true); Utils u = c.newInstance(); // Hello sailor 现在。。既然构造器看不见,怎么能测试它呢?这个测试能涵盖所有内容吗?@test @Test pub

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

private Utils() {
}
Constructor<Util> c = Utils.class.getDeclaredConstructor();
c.setAccessible(true);
Utils u = c.newInstance(); // Hello sailor
现在。。既然构造器看不见,怎么能测试它呢?这个测试能涵盖所有内容吗?

@test
@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);
}
公开的// void privateConstructorTest()引发异常{ 最终构造函数[]构造函数=Utils.class.getDeclaredConstructors(); //检查所有构造函数是否为“私有”: 对于(最终建造师:建造师){ Assert.assertTrue(Modifier.isPrivate(constructor.getModifiers()); } //调用私有构造函数: 构造函数[0]。setAccessible(true); 构造函数[0]。newInstance((对象[])null); }
使用反射,您可以调用私有构造函数:

private Utils() {
}
Constructor<Util> c = Utils.class.getDeclaredConstructor();
c.setAccessible(true);
Utils u = c.newInstance(); // Hello sailor
通过在构造函数中引发异常,可以阻止所有尝试


我也会让课程本身成为最终的,只是“因为”:


测试代码的意图。。始终:)

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

使用反射查询构造函数并验证它们是否设置了private属性

我会这样做:

@Test()
public void testPrivateConstructors() {
    final Constructor<?>[] constructors = Utils.class.getDeclaredConstructors();
    for (Constructor<?> constructor : constructors) {
        assertTrue(Modifier.isPrivate(constructor.getModifiers()));
    }
}
@Test()
public void testPrivateConstructors(){
最终构造函数[]构造函数=Utils.class.getDeclaredConstructors();
for(构造函数:构造函数){
assertTrue(Modifier.isPrivate(constructor.getModifiers());
}
}

如果您想对对象构造进行适当的测试,那么应该测试公共API,该API允许您获取构造的对象。这就是上述API应该存在的原因:为了正确地构建对象,您应该对此进行测试:)。

如果您有一个私有构造函数,它将从代码中一些不太私有的方法调用。所以你测试了这个方法,你的构造器也包括在内。对每种方法进行测试没有宗教美德。您正在寻找函数或更好的分支覆盖级别,只需通过使用构造函数的代码路径来练习构造函数,就可以得到它

如果代码路径复杂且难以测试,那么您可能需要重构它

以确保没有人错误地初始化此类的实例

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

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

  • 从默认的空构造函数中抛出UnsupportedOperationException(“不要实例化这个类!”)
  • 声明类抽象:如果它只包含静态方法,则可以调用静态方法,但不能实例化它,除非将其子类化
  • 或者同时应用1+2,如果测试与目标类共享同一个包,那么仍然可以子类化并运行构造函数。
    这应该是相当“防错”;恶意代码编写者总会找到解决方法:)

    如果在构造函数中添加异常,例如:

    private Utils() {
        throw new UnsupportedOperationException();
    }
    
    在测试类中调用
    constructor.newInstance()
    将抛出
    InvocationTargetException
    ,而不是
    UnsupportedOperationException
    ,但所需的异常将包含在抛出的异常中。
    如果您想断言抛出的您的异常,可以在捕获调用异常后抛出调用异常的目标。
    例如,使用jUnit 4可以做到以下几点:

    @Test(expected = UnsupportedOperationException.class)
    public void utilityClassTest() throws NoSuchMethodException, IllegalAccessException, InstantiationException {
        final Constructor<Utils> constructor = Utils.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        try {
            constructor.newInstance();
        } catch (InvocationTargetException e) {
            throw (UnsupportedOperationException) e.getTargetException();
        }
    }
    
    @Test(预期=UnsupportedOperationException.class)
    public void utilityClassTest()抛出NoSuchMethodException、IllegalAccessException、InstanceionException{
    最终构造函数=Utils.class.getDeclaredConstructor();
    constructor.setAccessible(true);
    试一试{
    构造函数。newInstance();
    }捕获(调用TargetException e){
    抛出(UnsupportedOperationException)e.getTargetException();
    }
    }
    
    不要这样做。构造函数是私有的。这就是你所需要的。Java强制执行其隐私


    不要测试平台。

    这会怎么样?你有例子吗?你没有。您可以使用私有构造函数测试该方法,但不是重复的。私有构造函数与私有构造函数截然不同methods@necromancer“非常不同”是如何实现的?我使用它将我的UTIL类的测试覆盖率提高到100%,这非常酷!感谢you@MrSmith42获得接近100%的测试覆盖率本身并不是一件事。测试覆盖率是一个指标。任何旨在改善指标而非实现实际结果的行动都会使指标贬值。毕竟,您可以让测试覆盖所有代码,这些测试使用所有方法,但不验证结果。所以,只有在有充分理由这样做的情况下,才可以通过直接调用私有构造函数来测试私有构造函数。(如果可能的话,最好通过调用工厂方法或类似的方法间接测试它)。无论如何,知道如何在需要的时候做这件事是很好的:-)@Alexey Tigarev:如果我有一个utils类,在这个类中,构造函数永远不会被调用,所有静态方法都会100%测试。所有调用过的方法都被测试覆盖,所以我希望覆盖工具也能报告类的100%覆盖率。如果这只能通过“测试”从未使用过的私有构造函数来实现,我建议这样做。+1。关于例外的观点非常好!美好的此外,如果添加了异常,那么也可能有理由为此进行单元测试。我发现UnsupportedOperationException比IllegalStateException更合适。@LuigiR.Viggiano没有什么好的观点。已更改为UnsupportedOperationException。Cheers@Ghashange不,但它进一步强化了读者的信息: