单元测试-如何在Java应用程序中测试私有构造函数?
这个问题已经在这里有了答案:
如何为私有构造函数添加测试覆盖率? 18个答案
如果一个类包含一堆静态方法,为了确保没有人错误地初始化该类的实例,我做了一个私有的构造函数:
private Utils() {
}
现在..鉴于无法看到构造函数,该如何进行测试? 可以测试吗?
JAM asked 2020-07-17T08:39:24Z
7个解决方案
68 votes
使用反射,您可以调用私有构造函数:
Constructor c = Utils.class.getDeclaredConstructor();
c.setAccessible(true);
Utils u = c.newInstance(); // Hello sailor
但是,您甚至可以做到这一点:
private Utils() {
throw new UnsupportedOperationException();
}
通过在构造函数中引发异常,可以防止所有尝试。
我也会自己创建类final,只是因为“因为”:
public final class Utils {
private Utils() {
throw new UnsupportedOperationException();
}
}
Bohemian answered 2020-07-17T08:39:50Z
19 votes
测试代码的意图..总是:)
例如:如果看不到构造函数是私有的,那么您需要测试的就是这个事实,仅此而已。
使用反射API查询构造函数,并验证它们是否具有私有属性集。
我会做这样的事情:
@Test()
public void testPrivateConstructors() {
final Constructor>[] constructors = Utils.class.getDeclaredConstructors();
for (Constructor> constructor : constructors) {
assertTrue(Modifier.isPrivate(constructor.getModifiers()));
}
}
如果要对对象构造进行适当的测试,则应该测试公共API,该API允许您获取构造的对象。 这就是上述API应该存在的原因:正确构建对象,因此您应该对此进行测试:)。
Mihai Toader answered 2020-07-17T08:40:28Z
6 votes
@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);
}
MrSmith42 answered 2020-07-17T08:40:46Z
5 votes
确保没有人错误地初始化此类的实例
通常,我要做的是将方法/构造函数从专用更改为默认程序包可见性。 而且我为测试类使用了相同的包,因此即使不是从外部,也可以从测试中访问方法/构造函数。
要强制策略不实例化类,您可以:
从默认的空构造函数中抛出UnsupportedOperationException(“不要实例化此类!”)。
声明类抽象:如果仅包含静态方法,则可以调用静态方法,但不能实例化它,除非您将其子类化。
或同时应用1 + 2,如果测试与目标类共享同一包,则仍可以继承并运行构造函数。这应该是相当“防错的”; 恶意编码人员总会找到解决方法的:)
Luigi R. Viggiano answered 2020-07-17T08:41:29Z
4 votes
如果您有私有构造函数,则从代码的某些非私有方法中调用它。 因此,您测试了该方法,并覆盖了构造函数。 每种方法进行测试没有宗教上的美德。 您正在寻找功能或更佳的分支覆盖级别,并且可以通过在使用该构造函数的代码路径中使用构造函数来简单地获得它。
如果该代码路径比较复杂且难以测试,则可能需要对其进行重构。
bmargulies answered 2020-07-17T08:41:54Z
3 votes
如果在构造函数中添加异常,例如:
private Utils() {
throw new UnsupportedOperationException();
}
在测试类中调用constructor.newInstance()将引发InvocationTargetException而不是UnsupportedOperationException,但是所需的异常将包含在引发的异常中。
如果要断言引发了异常,则可以在捕获到调用异常后引发调用异常的目标。
例如,使用jUnit 4,您可以执行以下操作:
@Test(expected = UnsupportedOperationException.class)
public void utilityClassTest() throws NoSuchMethodException, IllegalAccessException, InstantiationException {
final Constructor constructor = Utils.class.getDeclaredConstructor();
constructor.setAccessible(true);
try {
constructor.newInstance();
} catch (InvocationTargetException e) {
throw (UnsupportedOperationException) e.getTargetException();
}
}
Juan answered 2020-07-17T08:42:28Z
-3 votes
别。 构造函数是私有的。 这就是您所需要的。 Java强制执行其隐私。
不要测试平台。
user207421 answered 2020-07-17T08:42:52Z