1

以前に他の例外によってキャッチされてStandardUncaughtExceptionHandlerいない例外をキャッチするがあります。EventBus内部では、エラー処理に Guava を使用しています。アプリでスローされるチェック済み例外の種類ごとに、イベント ハンドラーをバスに登録して、その特定の例外の種類を処理します。バスが登録されたハンドラーを持たない例外をポストした場合、バスはその例外をDeadEventオブジェクトにラップし、デッド イベントをバスに再ポストします。これStandardUncaughtExceptionHandlerDeadEvents をリッスンするように登録されているため、キャッチされていない例外を常にチェックする方法が保証されます。

主なソースは次のとおりです。

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 を引き起こしている理由について何か考えはありますか? 私は確認して再確認しましたが、モックを正しく設定したと思います。前もって感謝します。

4

1 に答える 1

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このフィールドは、モックまたはその他の有効な方法を使用して、テスト メソッドで初期化する必要があります。

于 2013-02-11T21:29:44.703 に答える