Java:测试是否在更大的系统中捕获到异常

时间:2017-05-08 20:40:55

标签: java exception junit

我知道有很多关于这个主题的问题,但所有这些问题似乎都假设了两件事之一:

  1. 您只想测试是否抛出异常而未被捕获,
  2. 您应该测试try块内部的函数 直接
  3. 我不确定如何将这些选项应用于此案例。我有一个小的try / catch块,如下所示:

    try {
        o.getDataContainer().build(...);
        o2.setDataContainer(o.getDataContainer());
    } catch (final Exception e) {
        LOGGER.error("Data set failed", e);
    }
    

    如您所见,如果o.getDataContainer()返回null,则会触发异常。但是,然后捕获该异常,并且测试工具认为它是成功的测试。是否可以在不更改代码的情况下测试异常?

    我问,因为我们的日志记录系统会在遇到捕获并记录的异常时触发故障单。因为忘记保护这样的东西是常见的人为错误,所以我想编写可以测试异常是否被触发和捕获的UT。我无法删除catch块提供的整个程序保护,但错误也会导致用户体验下降,因为数据不会被传递。 (我在一个网站停机时间相等数百万美元的地方工作。)

    换句话说:异常是一个错误,我们想要记录并调查它,但是如果它设法触发prod,我们不想冒整个网站的风险。

    注意:这个try / catch位于一个更大的函数中,有很多这样的try / catch块。人们很容易认为整体设计不好,但修复它不是一种选择(至少没有大量的免费开发时间)。

    更新:由于手头的任务不允许我花费大量时间在这上面,所以我选择了一个非常简单的通用测试,如果后卫和捕获都被删除,那将会失败这样我就可以继续前进了。但是,我现在暂时没有回答这个问题,希望继续谈话。我希望能够为每个新功能编写一个简单的UT,如果触发和捕获任何异常,它将失败。

2 个答案:

答案 0 :(得分:0)

忽略这段代码的问题(我猜你有时会把口红放在猪身上),这就是我应对这种情况的方法。

我会使用Mockito并模拟o2,然后使用Answer来确保调用该方法。

测试可能如下所示:

@RunWith(MockitoJUnitRunner.class)
public class TestClass{
    @Mock
    O2 o2;
    @Mock
    O1 o1;

    boolean exceptionThrown = false;

    @Test
    public void test(){
        Mockito.doAnswer(new Answer<Void>(){     
           public Void answer(InvocationOnMock invocation) throws Throwable {
              exceptionThrown = true; 
           throw new RuntimeException("some message");
        }            
      }).when(o2).setDataContainer(DataContainer.class);
    }
}

基本上,您可以在示例中模拟o2,并强制执行异常。

如果这不是你想要的,你可能需要模拟LOGGER并验证它是否被LOGGER.error("some message");调用。不幸的是,嘲弄静态并不优雅,但可以用PowerMock完成。

答案 1 :(得分:0)

您可以向LOGGER添加自定义处理程序,该处理程序会在记录错误时抛出。对于java.util.logging,您可以执行以下操作:

LOGGER.addHandler(new Handler() {
    public void publish(LogRecord record) {
        if ("Data set failed".equals(record.getMessage())) {
            throw new RuntimeException(record.getThrown());
        }
    }
    public void flush() {}
    public void close() throws SecurityException {}
});

我认为log4j称之为“Appender”,但同样的原则应该有效。请参阅How to create a own Appender in log4j?How to Create a Custom Appender in log4j2?