我有以下课程:
public class FileLoader {
private Map<Brand, String> termsOfUseText = new HashMap<Brand, String>();
public void load() {
for (Brand brand : Brand.values()) {
readAndStoreTermsOfUseForBrand(brand);
}
}
private void readAndStoreTermsOfUseForBrand(Brand brand) {
String resourceName = "termsOfUse/" + brand.name().toLowerCase() + ".txt";
InputStream in = this.getClass().getClassLoader().getResourceAsStream(resourceName);
try {
String content = IOUtils.toString(in);
termsOfUseText.put(brand, content);
} catch (IOException e) {
throw new IllegalStateException(String.format("Failed to find terms of use source file %s", resourceName),e);
}
}
public String getTextForBrand(Brand brand) {
return termsOfUseText.get(brand);
}
}
Brand是一个枚举,我需要所有有效的.txt文件都在类路径上。如果Brand enum包含所有有效的品牌,并且所有的.txt文件都存在,那么如何使IOException发生呢?
有关重构当前代码的建议,如果它更容易测试,欢迎提出!
答案 0 :(得分:3)
我立即看到的三个选项:
答案 1 :(得分:1)
我建议您进行一些重构。您所有的方法都是 void ,这通常意味着它们不起作用。 例如,您可以提取此功能:
private String readTermsOfUseForBrand(InputStream termsOfUserIs) {
try {
String content = IOUtils.toString(in);
return content;
} catch (IOException e) {
throw new IllegalStateException(String.format("Failed to find terms of use source file %s", resourceName), e);
}
return null;
}
这样我们就可以在测试中对String结果进行断言。
当然,这不是功能代码,因为它是从输入流中读取的。而且它是通过IOUtils.toString()
方法实现的,该方法不容易被嘲笑(嗯,有PowerMock,但正如Ryan Stewart所说的,这是最后的手段)。
要测试IO异常,您可以创建一个失败的输入流(已通过JDK7测试):
public class FailingInputStream extends InputStream {
@Override
public int read() throws IOException {
throw new IOException("Test generated exception");
}
}
并像这样测试:
@Test
public void testReadTermsOfUseForBrand() {
FileLoader instance = new FileLoader();
String result = instance.readTermsOfUseForBrand(new FailingInputStream());
assertNull(result);
}
答案 2 :(得分:0)
缺少文件会导致NullPointerException
,因为getResourceAsStream
将返回null
,您将拥有in==null
。在这种情况下,IOException实际上可能非常罕见。如果你看到它是至关重要的,那么我只能想到如果在测试范围内执行代码,则将此代码用于抛出它。但它真的那么重要吗?
答案 3 :(得分:0)
我会用模拟来完成这个。
示例(未经测试,只是为了给你一些想法):
<?php
$change_reason = isset($_REQUEST["change_reason"]) ? $_REQUEST["change_reason"] : null;
if($change_reason){
switch ($change_reason) {
case 1:
echo '<p>Getting apple, OK!</p>
<textarea name="apples" rows="2">So I am getting some apples</textarea>';
break;
case 2:
echo '<p>Walking outside, OK!</p>
<textarea name="apples" rows="2">So I will walk outside now</textarea>';
break;
}
}
?>
答案 4 :(得分:-1)
以下代码完全未经测试 要导致IOException,请使用:
FileInputStream in = this.getClass().getClassLoader().getResourceAsStream(resourceName);
in.mark(0);
//read some data
in.reset(); //IOException
要测试IOException案例,请使用:
void test
{
boolean success = false;
try
{
//code to force ioException
}
catch(IOException ioex)
{
success = true;
}
assertTrue(success);
}
在JUnit4中
@Test(expected=IOException.class)
void test
{
//code to force ioException
}
其他JUnit
void test
{
try
{
//code to force IOException
fail("If this gets hit IO did not occur, fail test");
}
catch(IOException ioex)
{
//success!
}
}