Mockito 1.9.5导致NullPointerException

时间:2013-02-11 19:57:02

标签: java unit-testing nullpointerexception mockito

我有一个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的任何想法?我已经检查并重新检查了,我相信我已经正确设置了我的模拟。提前谢谢。

1 个答案:

答案 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。应使用模拟或任何其他有效方式在测试方法中初始化此字段。