如果一个类包含一堆静态方法,为了确保没有人错误地初始化该类的实例,我创建了一个私有构造函数:
private Utils() {
}
现在..如果不能看到构造函数,怎么可以测试呢?这可以覆盖测试吗?
答案 0 :(得分:68)
使用反射,可以调用私有构造函数:
Constructor<Util> 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();
}
}
答案 1 :(得分:19)
测试代码的意图..总是:)
例如:如果构造函数的私有点是不可见的,那么你需要测试的是这个事实,而不是别的。
使用反射API查询构造函数并验证它们是否具有私有属性集。
我会做这样的事情:
@Test()
public void testPrivateConstructors() {
final Constructor<?>[] constructors = Utils.class.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
assertTrue(Modifier.isPrivate(constructor.getModifiers()));
}
}
如果要对对象构造进行适当的测试,则应测试允许您获取构造对象的公共API。这就是所述API应该存在的原因:正确构建对象所以你应该测试它:)。
答案 2 :(得分: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);
}
答案 3 :(得分:5)
确保没有人错误地初始化此类的实例
通常我所做的是将方法/构造函数从私有更改为默认包可见性。我对我的测试类使用相同的包,因此从测试中可以访问方法/构造函数,即使它不是来自外部。
要强制执行策略以不实例化该类,您可以:
或同时应用1 + 2,如果您的测试与目标类共享相同的包,您仍然可以继承并运行构造函数。 这应该是非常“错误证明”;恶意程序员总能找到解决方法:)
答案 4 :(得分:4)
如果你有一个私有构造函数,它是从你的代码的一些不那么私有的方法调用的。因此,您测试该方法,并涵盖您的构造函数。对每种方法进行测试没有宗教信仰。您正在寻找功能或更好的分支覆盖级别,您只需通过使用它的代码路径来运行构造函数即可实现。
如果该代码路径错综复杂且难以测试,那么您可能需要对其进行重构。
答案 5 :(得分:3)
如果在构造函数中添加例外,例如:
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();
}
}
答案 6 :(得分:-3)
别。构造函数是私有的。这就是你所需要的。 Java强制实施其隐私。
不要测试平台。