在我的属性文件中放入什么值才能在加载时获得 IOException?
What values to put in my properties file to get an IOException while loading?
我正在从 Java 项目的类路径中读取一个文件。
示例代码:
public static Properties loadPropertyFile(String fileName) {
Properties properties = new Properties();
InputStream inputStream = PropertyReader.class.getClassLoader().getResourceAsStream(fileName);
if (inputStream != null) {
try {
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
} else {
throw new Exception("Property file: [" + fileName + "] not found in the classpath");
}
return properties;
}
一切正常。我正在为此代码编写 Junit 测试。如何在 properties.load(inputStream)
中为 IOException
创建场景?
我应该在 properties.file 中输入什么值才能得到 IOException
?
空的或无效的 fileName
参数。
传递一个空字符串作为文件名
当您查看 Properties::load
的实现时,您会发现 class 从不显式抛出异常。触发 IOException
的唯一方法是提交一个 InputStream
,它会在调用输入流的 read
方法时抛出此异常。
您可以控制 PropertyReader
class 吗?模拟此错误的一种方法是 instrument this class loader 到 return 给定测试值 fileName
的错误 InputStream
以抛出 IOException
。或者,您可以通过将签名更改为:
来使该方法更加灵活
public static Properties loadPropertyFile(String fileName) {
return loadPropertyFile(fileName, PropertyReader.class);
}
public static Properties loadPropertyFile(String fileName, ClassLoader cl) {
// your code...
}
用 class 加载程序:
class TestLoader extends ClassLoader {
@Override
public InputStream getResourceAsStream() {
return new InputStream() {
@Override
public byte read() throws IOException {
throws new IOException();
}
}
}
}
您不能将导致 IOException
的特定字符添加到属性文件中,因为 InputStream
仅读取字节。任何与编码相关的问题都会导致 IllegalArgumentException
.
你考虑过模拟框架吗?将属性的 new
运算符模拟为 return 一个模拟实现,当其 load
方法被调用时抛出 IOException
。
mockitio 和 powermockito 将允许您执行此操作。
强制 load
调用抛出 IOException
的一种方法是传递一个关闭的流。如果您可以重构您的方法以接受 InputStream
,您可以将一个关闭的流传递给该方法并检查它是否抛出异常。
也就是说,单元测试应该涵盖您编写的代码。在我看来,如果输入流有错误,您正在测试 load
是否抛出异常。这是多余的。
我知道这是一个旧线程,但自从我最近 运行 遇到同样的问题并基于 我想出了这个测试:
@Test
void testFailLoadProjectFile() throws NoSuchMethodException, SecurityException {
final var method = LogGeneratorComponent.class.getDeclaredMethod("loadProjectProperties", Properties.class);
Assertions.assertTrue(Modifier.isPrivate(method.getModifiers()), "Method is not private.");
method.setAccessible(true);
final var obj = new LogGeneratorComponent();
Assertions.assertThrows(InvocationTargetException.class, () -> method.invoke(obj, new Properties() {
private static final long serialVersionUID = 5663506788956932491L;
@Override
public synchronized void load(@SuppressWarnings("unused") final InputStream is) throws IOException {
throw new IOException("Invalid properties implementation.");
}
}), "An InvocationTargetException should have been thrown, but nothing happened.");
}
这是我的实际方法:
private static Properties loadProjectProperties(final Properties properties) {
try (final var is = Thread.currentThread().getContextClassLoader().getResourceAsStream("project.properties")) {
properties.load(is);
return properties;
} catch (final IOException e) {
throw new UncheckedIOException("Error while reading project.properties file.", e);
}
}
显然 OP 可以自定义它以接收 fileName 参数并使其成为 public 以便进行更简单的测试。
我正在从 Java 项目的类路径中读取一个文件。
示例代码:
public static Properties loadPropertyFile(String fileName) {
Properties properties = new Properties();
InputStream inputStream = PropertyReader.class.getClassLoader().getResourceAsStream(fileName);
if (inputStream != null) {
try {
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
} else {
throw new Exception("Property file: [" + fileName + "] not found in the classpath");
}
return properties;
}
一切正常。我正在为此代码编写 Junit 测试。如何在 properties.load(inputStream)
中为 IOException
创建场景?
我应该在 properties.file 中输入什么值才能得到 IOException
?
空的或无效的 fileName
参数。
传递一个空字符串作为文件名
当您查看 Properties::load
的实现时,您会发现 class 从不显式抛出异常。触发 IOException
的唯一方法是提交一个 InputStream
,它会在调用输入流的 read
方法时抛出此异常。
您可以控制 PropertyReader
class 吗?模拟此错误的一种方法是 instrument this class loader 到 return 给定测试值 fileName
的错误 InputStream
以抛出 IOException
。或者,您可以通过将签名更改为:
public static Properties loadPropertyFile(String fileName) {
return loadPropertyFile(fileName, PropertyReader.class);
}
public static Properties loadPropertyFile(String fileName, ClassLoader cl) {
// your code...
}
用 class 加载程序:
class TestLoader extends ClassLoader {
@Override
public InputStream getResourceAsStream() {
return new InputStream() {
@Override
public byte read() throws IOException {
throws new IOException();
}
}
}
}
您不能将导致 IOException
的特定字符添加到属性文件中,因为 InputStream
仅读取字节。任何与编码相关的问题都会导致 IllegalArgumentException
.
你考虑过模拟框架吗?将属性的 new
运算符模拟为 return 一个模拟实现,当其 load
方法被调用时抛出 IOException
。
mockitio 和 powermockito 将允许您执行此操作。
强制 load
调用抛出 IOException
的一种方法是传递一个关闭的流。如果您可以重构您的方法以接受 InputStream
,您可以将一个关闭的流传递给该方法并检查它是否抛出异常。
也就是说,单元测试应该涵盖您编写的代码。在我看来,如果输入流有错误,您正在测试 load
是否抛出异常。这是多余的。
我知道这是一个旧线程,但自从我最近 运行 遇到同样的问题并基于
@Test
void testFailLoadProjectFile() throws NoSuchMethodException, SecurityException {
final var method = LogGeneratorComponent.class.getDeclaredMethod("loadProjectProperties", Properties.class);
Assertions.assertTrue(Modifier.isPrivate(method.getModifiers()), "Method is not private.");
method.setAccessible(true);
final var obj = new LogGeneratorComponent();
Assertions.assertThrows(InvocationTargetException.class, () -> method.invoke(obj, new Properties() {
private static final long serialVersionUID = 5663506788956932491L;
@Override
public synchronized void load(@SuppressWarnings("unused") final InputStream is) throws IOException {
throw new IOException("Invalid properties implementation.");
}
}), "An InvocationTargetException should have been thrown, but nothing happened.");
}
这是我的实际方法:
private static Properties loadProjectProperties(final Properties properties) {
try (final var is = Thread.currentThread().getContextClassLoader().getResourceAsStream("project.properties")) {
properties.load(is);
return properties;
} catch (final IOException e) {
throw new UncheckedIOException("Error while reading project.properties file.", e);
}
}
显然 OP 可以自定义它以接收 fileName 参数并使其成为 public 以便进行更简单的测试。