如何在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应该存在的原因:为了正确地构建对象,您应该对此进行测试:)。如果您有一个私有构造函数,它将从代码中一些不太私有的方法调用。所以你测试了这个方法,你的构造器也包括在内。对每种方法进行测试没有宗教美德。您正在寻找函数或更好的分支覆盖级别,只需通过使用构造函数的代码路径来练习构造函数,就可以得到它 如果代码路径复杂且难以测试,那么您可能需要重构它 以确保没有人错误地初始化此类的实例 通常我要做的是将方法/构造函数从私有更改为默认包可见性。我对我的测试类使用相同的包,因此从测试中可以访问方法/构造函数,即使它不是从外部访问的 要强制策略不实例化该类,可以:
这应该是相当“防错”;恶意代码编写者总会找到解决方法:)如果在构造函数中添加异常,例如:
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不,但它进一步强化了读者的信息: