强制FileNotFoundException

时间:2009-03-02 23:10:56

标签: java junit testing ioexception filenotfoundexception

我正在为一段代码编写测试,其中包含一个IOException catch,我试图覆盖它。 try / catch看起来像这样:

try {
    oos = new ObjectOutputStream(new FileOutputStream(cacheFileName));
} catch (IOException e) {
    LOGGER.error("Bad news!", e);
} finally {

最简单的方法似乎是让FileOutputStream抛出一个FileNotFoundException,但也许我会以错误的方式解决这个问题。

有人在那里有任何提示吗?

9 个答案:

答案 0 :(得分:5)

您可以将cacheFileName设置为无效名称或您知道不存在的名称。

答案 1 :(得分:4)

来自你的评论:

  

是的,我想问题应该是   真的是“我怎么创造一个   两个Linux上都不存在的文件   和Windows?“在Windows上,我可以使用   'new File(“X:/”)',其中X:是一个驱动器   不存在的信件。在Linux上,   这不起作用,因为那是一个   有效的文件名。

查看java.io.File.createTempFile。使用它来创建文件,然后将其删除。

可能会传递类似:

File tempFile;

tempFile = createTempFile(getClass().getName(), 
                          Long.toString(System.currentTimeMillis());
tempFile.delete();

这应该以平台的方式为您提供一个独特的名称,您可以安全地使用它,而不必担心它存在。

答案 2 :(得分:2)

任何测试都有两个部分:让它发生并测量你得到了正确的结果。

故障注入

最简单的答案是已经提到的答案,即将cacheFileName设置为永不存在的文件。在这种情况下,这可能是最实际的答案。

但是,要导致诸如IOException之类的任意条件,您真正想要的是Fault Injection。这会强制您的代码中的错误,而不会强制您检测源代码。以下是一些执行此操作的方法:

  • 模拟对象您可以使用工厂方法创建被覆盖的ObjectOutputStreamFileOutputStream。在测试代​​码中,实现将在您想要时抛出IOException,并且在生产代码中不会修改正常行为。
  • 依赖注入为了让您的Mock对象在正确的位置,您可以使用SpringSeam之类的框架将适当的对象“注入”到正在做这项工作的班级。您可以看到这些框架甚至对要注入的对象具有优先级,因此在单元测试期间,您可以使用测试对象覆盖生产对象。
  • Aspect Oriented Programming 您可以使用AOP在正确的位置注入错误,而不是更改代码的结构。例如,使用AspectJ,您可以定义一个Pointcut,您希望抛出异常,并让Advice抛出所需的异常。

Java上还有其他错误注入的答案;例如,一个名为AProbe的产品很早就开创了C语言中的AOP,它们也有Java产品。

验证

抛出异常是一个好的开始,但您还必须验证您是否获得了正确的结果。假设您拥有的代码示例是正确的,您希望验证您是否记录了该异常。上面提到的人使用Mock对象作为记录器,这是一个可行的选择。您也可以在此处使用AOP来捕获对记录器的调用。

我假设记录器是log4j;为了解决类似的问题,我实现了自己的log4j appender,它捕获log4j输出:我专门捕获ERRORFATAL,在这种情况下可能是有趣的日志消息。 appender在log4j.xml中引用,并在测试运行期间激活以捕获错误日志输出。这本质上是一个模拟对象,但我没有重构我的所有得到log4j Logger的代码。

答案 3 :(得分:0)

  

我正在为一段代码编写测试   其中有一个IOException catch   我试图报道。

我不完全确定我理解你的目标,但是如果你想测试是否抛出异常,你可以告诉测试你希望它抛出异常:

@Test(expected=IOException.class)

如果未抛出异常,您的测试将失败,如果抛出异常则成功(例如,如果cacheFileName文件不存在)。

答案 4 :(得分:0)

FileNotFoundException显然会触发catch。 javadoc说明了它将被抛出的情况。

您还应该考虑ObjectOutputStream构造函数可以抛出IOException,因此可能希望在测试中涵盖这种情况。

答案 5 :(得分:0)

两种简单的方法是将cacheFileName设置为不存在的文件,或将指定的文件设置为只读访问。

-John

答案 6 :(得分:0)

由于代码当前已编写,您可以尝试模拟对LOGGER对象的error()调用,并检查在期望IOException时是否调用它。

您的测试愿望可能已经发现了代码的基本问题。发生错误但没有布尔值或标志值(将文件名设置为特殊模式),该值提供其他代码段以确定写入文件是否成功。如果它包含在函数中,则可能返回布尔值或设置对象级变量。

答案 7 :(得分:0)

cacheFileName = "thisFileShouldNeverExistAndIfItDoesYouAreScrewingUpMyTests";

当然,您可以采取措施并通过箍跳以编程方式确保文件名永远不会存在,或者您可以使用在99.99999%的情况下永远不会存在的字符串。

答案 8 :(得分:0)

我希望这就是你的意思。

if(new File(cachedFile).exists()) {
    oos = new ObjectOutputStream(new FileOutputStream(cacheFileName));
    //do your code here
} else {
    throw new FileNotFoundException("File doesn't exist!");
}
相关问题