我知道有很多关于这个主题的问题,但所有这些问题似乎都假设了两件事之一:
我不确定如何将这些选项应用于此案例。我有一个小的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,如果触发和捕获任何异常,它将失败。
答案 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?