I have a StandardUncaughtExceptionHandler
which catches any exceptions that haven't been previously caught by other exceptions. Under the hood, I'm using a Guava EventBus
for error handling. For each type of checked exception thrown in my app, I register an event handler with the bus to handle that specific exception type. If the bus posts an exception that it doesn't have a registered handler for, it wraps that exception in a DeadEvent
object, and reposts the dead event back to the bus. This StandardUncaughtExceptionHandler
is registered to listen for DeadEvent
s, guaranteeing me that I'll always have a way to check for uncaught exceptions.
Here's the main source:
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());
}
}
And my test for it, checking to make sure that when we give it a Throwable
that it constructs the correct log message.
@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"));
}
}
When I run this test, I get the following error in my JUnit console:
java.lang.NullPointerException
at com.myapp.StandardUncaughtExceptionHandlerTest.handleUncaughtExceptionLogsThrowableIfPresent(StandardUncaughtExceptionHandlerTest.java:63)
... rest of stack trace omitted for brevity, it's huge
Any ideas as to why Mockito is causing the NPEs? I've checked and rechecked and I believe I've set my mocks up correctly. Thanks in advance.
Mockito is not the issue here.
I believe the NPE is reported in the following line of your test:
Assert.assertTrue(rte.getMessage().contains("Logging-Throwable"));
because rte.getMessage()
returns null
. Unfortunately due to the try-catch
block in your unit test, the real origin of this error is hidden from you. Uncommenting try-catch
in handleUncaughtExceptionLogsThrowableIfPresent()
reveals the real issue: a NPE is thrown in the following line:
loggingService.error(logBuilder.toString());
because loggingService
is never initialized in the StandardUncaughtExceptionHandler
class. This field should be initialized in your test method with the mock or in any other valid way.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.