【问题标题】:Junit not catching FileNotFoundExceptionJunit 没有捕获 FileNotFoundException
【发布时间】:2019-08-13 11:42:02
【问题描述】:

我遇到了一些奇怪的事情。我有一种方法可以逐行读取 CSV 文件。该方法采用 filePath,在我的 JUnit 测试中,我正在使用错误的 filePath 测试此方法,期望得到 FileNotFoundException。问题是 JUnit5 没有抛出那个异常,但是在 eclipse 控制台中我可以看到 JVM 抛出了那个异常,所以我很难理解为什么

我已经设置了我的测试代码来抛出异常,但它没有被抛出。我试图捕捉异常,但仍然没有乐趣。

这里是方法和测试方法

public void readData(String COMMA_DELIMITER, String READ_FILE_PATH) {
    BufferedReader br = null;
    try {
        br = new BufferedReader(new FileReader(READ_FILE_PATH));
        String line = "";
        //Read to skip the header
        br.readLine();
        //Reading from the second line
        while ((line = br.readLine()) != null) 
        {

            String[] employeeDetails = line.split(COMMA_DELIMITER);
            populateModel(employeeDetails);
        }

        //Lets print the Employee List
        for(Employee e : empList)
        {
            System.out.println(e.getName() + "; " + e.getSurname() + "; " + e.getDateOfBirth() + "; " + e.getSex());
        }


    } 
    catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    catch (IOException e) {
        e.printStackTrace();
    }

}

@Test
    void testWrongFilePath() {
        String READ_FILE_PATH_WRONG = System.getProperty("user.dir") + "/teest/XXXFile.csv";
        System.out.println(READ_FILE_PATH_WRONG);
        Assertions.assertThrows(FileNotFoundException.class, () -> {
            readData.readData(COMMA_DELIMITER, READ_FILE_PATH_WRONG);
        });     
    }

在控制台中,我得到了 FIleNotFOundException,但测试的输出显示

org.opentest4j.AssertionFailedError: Expected java.io.FileNotFoundException to be thrown, but nothing was thrown.

【问题讨论】:

  • 你已经抓住了FileNotFoundException,这意味着它不会被方法抛出。尽量不要抓住它,也许用throws FileNotFoundException注释方法。
  • 好的,谢谢,我按照建议添加了throws FileNotFoundException,但我当然必须将调用者 - 在 main 方法中 - 在 try 和 catch 语句中。现在,通过这种方式我们可以让测试工作,这很好,但我的直觉——这当然可能是错误的——似乎表明在 readData 方法中捕获异常比在调用者中捕获它们更好。你怎么看?
  • 当然更好,但是你的方法不会抛出FileNotFoundException,这意味着在这种情况下你必须返回一些有意义的东西。关于boolean 返回值的建议还不错,我认为你可以这样做。使方法在捕获异常的catch 块中返回booleanreturn false;。返回boolean 表示执行的操作是否成功是一种常见的做法。
  • 捕获异常不是更好!当其他代码调用您的方法时,他们希望它已成功读取数据。如果该方法无法成功完成其任务,它需要让调用者知道这一点, 而做到这一点的最佳方法是让 FileNotFoundException 传播,或者将其包装在特定于应用程序的例外。
  • @deHaar 将捕获的异常作为新 RuntimeException 的原因肯定比抑制或仅打印/记录异常要好。是否是最好的方法在很大程度上取决于方法的性质和捕获的异常的性质。

标签: java unit-testing junit5


【解决方案1】:

您不能期望您的断言框架能够捕获在您的 SUT 中捕获的异常:

catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

你要么必须:

  • 记录然后重新抛出相同/不同的异常并断言。

  • 使您的方法返回布尔值作为成功等效项,然后您可以对其进行断言。

【讨论】:

    【解决方案2】:

    您在readData 中捕获FileNotFoundException

    尝试重构,让你没有try-catch,并且有public void readData(String COMMA_DELIMITER, String READ_FILE_PATH) throws IOException { ...

    FileNotFoundExceptionIOException 的子类。)

    【讨论】:

      【解决方案3】:
      assertThrows(Class<T> expectedType, Executable executable)
      

      不会断言在您的代码中一次抛出异常(在您的情况下是这样)。但这断言在 Executable lambda 中调用的语句会引发异常(在您的情况下是错误的)。

      由于您在被测方法中捕获了FileNotFoundException,因此该异常永远不会传播到 lambda 返回,并且 JUnit 只能发出错误,因为没有遇到预期的异常。

      要断言这样的事情,不要通过删除catch 语句来捕获异常,而不是在被测方法的声明中声明throws FileNotFoundException

      public void readData(String COMMA_DELIMITER, String READ_FILE_PATH) throw FileNotFoundException {...}
      

      【讨论】:

        【解决方案4】:

        您的方法没有抛出FileNotFoundException:您捕获它,打印堆栈跟踪,并继续进行,就好像没有发生异常一样:

        catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        

        JUnit 并不神奇:它无法检测方法内部发生的事情,只能检测副作用(返回的值、未捕获的异常、变异状态)。

        【讨论】:

          猜你喜欢
          • 2018-02-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多