如果一个类包含一堆静态方法,为了确保没有人错误地初始化这个类的实例,我做了一个私有构造函数:
private Utils() {
}
现在.. 鉴于构造函数看不到,这怎么能被测试?这完全可以被测试覆盖吗?
如果一个类包含一堆静态方法,为了确保没有人错误地初始化这个类的实例,我做了一个私有构造函数:
private Utils() {
}
现在.. 鉴于构造函数看不到,这怎么能被测试?这完全可以被测试覆盖吗?
使用反射,您可以调用私有构造函数:
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();
}
}
测试代码的意图..总是:)
例如:如果构造函数的点是私有的,那么你需要测试的是这个事实,而不是别的。
使用反射API查询构造函数并验证它们是否具有私有属性集。
我会做这样的事情:
@Test()
public void testPrivateConstructors() {
final Constructor<?>[] constructors = Utils.class.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
assertTrue(Modifier.isPrivate(constructor.getModifiers()));
}
}
如果您想对对象构造进行适当的测试,您应该测试允许您获取构造对象的公共 API。这就是上述 API 应该存在的原因:正确构建对象,因此您应该对其进行测试:)。
@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);
}
确保没有人错误地初始化此类的实例
通常我所做的是将方法/构造函数从私有更改为默认包可见性。而且我对我的测试类使用相同的包,所以从测试中可以访问方法/构造函数,即使它不是来自外部。
要强制执行不实例化类的策略,您可以:
或者同时应用 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();
}
}
不。构造函数是私有的。这就是你所需要的。Java 强制执行其隐私。
不要测试平台。