首页 > 解决方案 > 如何检查 JUnit 中的异常处理?

问题描述

如果发生错误,实际上会发生异常情况。如何进行测试以检查是否确实发生了异常?

 private String getTemplate(String templateName) {
    try {
        FileReader reader = new FileReader(
                getClass().getClassLoader().getResource("templates/" 
                   + templateName).getFile()
        );
        StringBuilder templateString = new StringBuilder();

        char[] symbol = new char[256];
        int readBytes;
        while((readBytes = reader.read(symbol)) > 0)
            for (int i = 0; i < readBytes; i++)
                templateString.append(symbol[i]);

        return templateString.toString();
    } catch (NullPointerException e) {
        e.printStackTrace();
        return "{'detail': 'internal server error: page not found'}";
    }  catch (IOException e) {
        e.printStackTrace();
        return "{'detail': 'internal server error: page cannot be read'}";
    }
}

标签: java

解决方案


基本上你的问题是你很难编写测试代码:

    FileReader reader = new FileReader(
            getClass().getClassLoader().getResource("templates/" 
               + templateName).getFile()

这个对 new 的调用基本上转化为:如果需要的话,您需要 PowerMock(ito) 或 JMockit 来控制您的生产代码。

您可以改为:FileReader 对象传递给该方法,以便它只调用该对象上的方法。然后您可以使用 Mockito 为该代码提供一个模拟的FileReader。通过这样做,您可以控制测试生产代码时发生的情况。

然后你可以做类似的事情:

@Test
public void testNPE() {
  Mockito.when(mockedFileReader.read(ArgumentsMatcher.any())).thenThrow(new NullPointerException("haha"));
  String result = objectUnderTest.callAPublicMethodThatCallsTheMethodUnderTest(foo);

  assertThat(result, is("{'detail': 'internal server error: page not found'}");
  }

上面指示模拟文件阅读器在调用其 read() 方法时抛出 NPE。然后您会期望您的生产代码返回该字符串。

如您所见,您必须“填充”很多东西:

  • 你不能调用私有方法,所以很明显,你必须调用一个公共入口点到你的测试类
  • 它仅在来自私有方法的字符串以某种方式出现在该公共方法的响应中时才有效
  • 并且,如前所述:模拟文件阅读器需要以某种方式进入objectUnderTest

最后:捕获 NPE 是一个非常糟糕的主意,并假设这意味着“找不到页面”。空指针就是这样:对空的引用。如果有的话,您的代码应该检查某些条件以得出“找不到页面”的结论。NPE 发生的原因有很多。可能存在代码错误,您去告诉客户“找不到页面”?!

因此,真正的答案是不同的:你应该退后一步,做很多研究,你如何进行适当的单元测试,也许使用像 Mockito 这样的框架。然后您将学习如何编写易于测试的代码。如前所述:您编写的代码基本上是不可测试的。您最好解决这个问题,而不是希望一些神奇的框架可以帮助您解决代码库的固有问题。


推荐阅读