我有一个StandardUncaughtExceptionHandler
可以捕获之前未被其他异常捕获的任何异常。在引擎盖下,我使用Guava EventBus
进行错误处理。对于我的应用程序中抛出的每种类型的已检查异常,我使用总线注册一个事件处理程序来处理该特定异常类型。如果总线发布了一个没有注册处理程序的异常,它会将该异常包装在DeadEvent
对象中,并将死事件重新发送回总线。此StandardUncaughtExceptionHandler
已注册,可以收听DeadEvent
,以保证我始终可以检查未捕获的例外情况。
以下是主要来源:
public class StandardUncaughtExceptionHandler implements UncaughtExceptionHandler {
private LoggingService loggingService;
// Getter and setter for logginService.
@Override @Subscribe
public void handleUncaughtException(DeadEvent deadEvent) {
// Log it.
StringBuilder logBuilder = new StringBuilder();
if(deadEvent.getEvent() instanceof Throwable) {
Throwable throwable = (Throwable)deadEvent.getEvent();
logBuilder.append("An uncaught exception occurred: ");
logBuilder.append(throwable.getMessage());
logBuilder.append(" - Stack trace: ");
logBuilder.append(throwable.getStackTrace());
}
else
logBuilder.append("Something weird happened.");
loggingService.error(logBuilder.toString());
}
}
我的测试,检查以确保当我们给它一个Throwable
时,它构造了正确的日志消息。
@Test
public void handleUncaughtExceptionLogsThrowableIfPresent() {
// GIVEN
StandardUncaughtExceptionHandler fixture =
new StandardUncaughtExceptionHandler();
LoggingService mockLoggingService = Mockito.mock(LoggingService.class);
DeadEvent mockDeadEvent = Mockito.mock(DeadEvent.class);
Mockito.doThrow(new RuntimeException("Logging-Throwable"))
.when(mockLoggingService)
.error(Mockito.contains("An uncaught exception occurred:"));
Mockito.doThrow(new RuntimeException("Logging-Something-Else"))
.when(mockLoggingService)
.error(Mockito.contains("Something weird happened."));
Mockito.doReturn(new Throwable()).when(mockDeadEvent).getEvent();
try {
// WHEN
fixture.handleUncaughtException(mockDeadEvent);
Assert.fail();
} catch(RuntimeException rte) {
// THEN
Assert.assertTrue(rte.getMessage().contains("Logging-Throwable"));
}
}
当我运行此测试时,我在JUnit控制台中收到以下错误:
java.lang.NullPointerException
at com.myapp.StandardUncaughtExceptionHandlerTest.handleUncaughtExceptionLogsThrowableIfPresent(StandardUncaughtExceptionHandlerTest.java:63)
... rest of stack trace omitted for brevity, it's huge
关于为什么Mockito导致NPE的任何想法?我已经检查并重新检查了,我相信我已经正确设置了我的模拟。提前谢谢。
答案 0 :(得分:3)
Mockito不是问题所在。
我相信NPE会在您的测试的以下行中报告:
Assert.assertTrue(rte.getMessage().contains("Logging-Throwable"));
因为rte.getMessage()
返回null
。不幸的是,由于您的单元测试中存在try-catch
块,因此隐藏了此错误的真正原因。在try-catch
中取消注释handleUncaughtExceptionLogsThrowableIfPresent()
会显示真正的问题:NPE会出现在以下行中:
loggingService.error(logBuilder.toString());
因为loggingService
类中永远不会初始化StandardUncaughtExceptionHandler
。应使用模拟或任何其他有效方式在测试方法中初始化此字段。