单元测试已捕获并处理异常

时间:2015-01-27 15:28:58

标签: java unit-testing exception mocking mockito

我编写了一个使用BufferedReader和FileReader的方法,结果是需要处理FileNotFoundException和IOException。

现在我已经在我的类中使用了try和catch语句来处理异常,所以没有问题。

我遇到的问题是编写一个测试,以验证是否已捕获异常。

我不能按如下方式编写测试,因为我的方法已捕获异常,因此它不会传播到测试中处理:

@Test(expected = FileNotFoundException.class)
public void testFileNotFound() {
    ...
};

我如何测试异常是否被捕获?我是否需要创建我的类的模拟对象并验证是否已使用Mockitio之类的东西捕获到异常?或者不创建模拟并使用Mockitio监视实际对象以验证是否已捕获异常?

编辑:这是我要测试的方法......

public List<String[]> parse(String fileToRead) {

    BufferedReader fileReader = null;
    List<String[]> parsedData = new ArrayList<String[]>();
    String currentLine;

    try {
        fileReader = new BufferedReader(new FileReader(fileToRead));

        while ((currentLine = fileReader.readLine()) != null) {
            String[] parsedLine = currentLine.split(",");
            parsedData.add(parsedLine);
        }
    }
    catch (FileNotFoundException e) {
        logger.error("File does not exist", e);
    }
    return parsedData;
}

1 个答案:

答案 0 :(得分:2)

我认为这是尝试反对语言的经典例子,而不是使用它。它也可能是代码的一个例子,它不能通过设计进行测试。

首先,理解已检查和未检查的异常之间的概念区别非常重要。未经检查的例外情况如NullPointerExceptionArrayIndexOutOfBoundsException是&#34;未选中&#34; (意思是编译器并不关心它们),因为当它们被抛出时,通常是程序员的错。在方法调用之前使用if语句通常可以轻松防止这些异常。另一方面,IOExceptionFileNotFoundException被检查&#34; (意味着编译器会抱怨缺少catch / throw),因为即使您在尝试读取文件之前检查文件是否存在File#exists()方法,同时也可能发生外部事件导致文件丢失,或者当您正在读取其上的文件时,可能会从机器中拔出硬盘。检查异常通常表示一种崩溃状态,您必须专门决定如何从中恢复,并且只有您(作为程序员)才能做出决定。

考虑你的方法。如何通过方法的输出来判断读取操作是否失败或是否为空文件?你不能,因为即使这两个事件完全不同,你也会以完全相同的方式处理它们。这可能是您想要的,也可能不是,但处理这两种情况可能与您调用该方法的方式不同。例如,您可能希望向用户显示一条消息&#34;文件为空&#34;或者那个&#34;文件不存在&#34;而不是&#34;没有数据&#34;。

其次,可测试性问题(可能是也可能不是问题,具体取决于您的设置)。在catch - 子句中发生的唯一事情(因此是抛出和捕获异常的唯一指示)是臭名昭着的记录和忘记&#34;战略。您正在记录错误(而不是在适当的情况下处理/响应它),因此要验证是否捕获了异常,您唯一真正的选择是模拟记录器(如果您的设计允许)并验证其error()方法被称为。如果您的目标是验证在给定某个输入时抛出异常,则您无法检查输出,因为这只是验证输出 - 完全不同的测试。您必须检查抛出异常产生的代码路径,在这种情况下,一种方法是模拟记录器。