@Test public void processError_returns_value_of_processUnhandledError_if_riposteErrorHandler_explodes() throws UnexpectedMajorErrorHandlingError, JsonProcessingException { // given HttpProcessingState stateMock = mock(HttpProcessingState.class); Object msg = new Object(); Throwable cause = new Exception(); ExceptionHandlingHandler handlerSpy = spy(handler); ResponseInfo<ErrorResponseBody> responseInfoMockFromCatchallMethod = mock(ResponseInfo.class); doThrow(new RuntimeException()).when(riposteErrorHandlerMock).maybeHandleError(any(), any()); doReturn(responseInfoMockFromCatchallMethod).when(handlerSpy).processUnhandledError(stateMock, msg, cause); // when ResponseInfo<ErrorResponseBody> response = handlerSpy.processError(stateMock, msg, cause); // then verify(riposteErrorHandlerMock).maybeHandleError(any(), any()); assertThat(response, is(responseInfoMockFromCatchallMethod)); }
@Test public void processError_returns_value_of_processUnhandledError_if_riposteErrorHandler_returns_null() throws UnexpectedMajorErrorHandlingError, JsonProcessingException { // given HttpProcessingState stateMock = mock(HttpProcessingState.class); Object msg = new Object(); Throwable cause = new Exception(); ExceptionHandlingHandler handlerSpy = spy(handler); ResponseInfo<ErrorResponseBody> responseInfoMockFromCatchallMethod = mock(ResponseInfo.class); doReturn(null).when(riposteErrorHandlerMock).maybeHandleError(any(), any()); doReturn(responseInfoMockFromCatchallMethod).when(handlerSpy).processUnhandledError(stateMock, msg, cause); // when ResponseInfo<ErrorResponseBody> response = handlerSpy.processError(stateMock, msg, cause); // then verify(riposteErrorHandlerMock).maybeHandleError(any(), any()); assertThat(response, is(responseInfoMockFromCatchallMethod)); }
/** * Attempts to process the given error using the "normal" error handler {@link #riposteErrorHandler} to produce the * most specific error response possible for the given error. If that fails for any reason then the unhandled error * handler will take over to guarantee the user gets a generic error response that still follows our error contract. * If you already know your error is a non-normal unhandled error of the "how did we get here, this should never * happen" variety you can (and should) directly call {@link #processUnhandledError(HttpProcessingState, Object, * Throwable)} instead. */ protected ResponseInfo<ErrorResponseBody> processError(HttpProcessingState state, Object msg, Throwable cause) { RequestInfo<?> requestInfo = getRequestInfo(state, msg); try { ErrorResponseInfo contentFromErrorHandler = riposteErrorHandler.maybeHandleError(cause, requestInfo); if (contentFromErrorHandler != null) { // The regular error handler did handle the error. Setup our ResponseInfo. ResponseInfo<ErrorResponseBody> responseInfo = new FullResponseInfo<>(); setupResponseInfoBasedOnErrorResponseInfo(responseInfo, contentFromErrorHandler); return responseInfo; } } catch (Throwable errorHandlerFailed) { logger.error("An unexpected problem occurred while trying to handle an error.", errorHandlerFailed); } // If we reach here then it means the regular handler didn't handle the error (or blew up trying to handle it), // so the riposteUnhandledErrorHandler should take care of it. return processUnhandledError(state, msg, cause); }
/** * Attempts to process the given error using the "normal" error handler {@link #riposteErrorHandler} to produce the * most specific error response possible for the given error. If that fails for any reason then the unhandled error * handler will take over to guarantee the user gets a generic error response that still follows our error contract. * If you already know your error is a non-normal unhandled error of the "how did we get here, this should never * happen" variety you can (and should) directly call {@link #processUnhandledError(HttpProcessingState, Object, * Throwable)} instead. */ protected ResponseInfo<ErrorResponseBody> processError(HttpProcessingState state, Object msg, Throwable cause) { RequestInfo<?> requestInfo = getRequestInfo(state, msg); try { ErrorResponseInfo contentFromErrorHandler = riposteErrorHandler.maybeHandleError(cause, requestInfo); if (contentFromErrorHandler != null) { // The regular error handler did handle the error. Setup our ResponseInfo. ResponseInfo<ErrorResponseBody> responseInfo = new FullResponseInfo<>(); setupResponseInfoBasedOnErrorResponseInfo(responseInfo, contentFromErrorHandler); return responseInfo; } } catch (Throwable errorHandlerFailed) { logger.error("An unexpected problem occurred while trying to handle an error.", errorHandlerFailed); } // If we reach here then it means the regular handler didn't handle the error (or blew up trying to handle it), // so the riposteUnhandledErrorHandler should take care of it. return processUnhandledError(state, msg, cause); }
@Test public void processError_gets_requestInfo_then_calls_riposteErrorHandler_then_converts_to_response_using_setupResponseInfoBasedOnErrorResponseInfo() throws UnexpectedMajorErrorHandlingError, JsonProcessingException { // given HttpProcessingState stateMock = mock(HttpProcessingState.class); Object msg = new Object(); Throwable cause = new Exception(); ExceptionHandlingHandler handlerSpy = spy(handler); RequestInfo<?> requestInfoMock = mock(RequestInfo.class); ErrorResponseInfo errorResponseInfoMock = mock(ErrorResponseInfo.class); RiposteErrorHandler riposteErrorHandlerMock = mock(RiposteErrorHandler.class); Whitebox.setInternalState(handlerSpy, "riposteErrorHandler", riposteErrorHandlerMock); doReturn(requestInfoMock).when(handlerSpy).getRequestInfo(stateMock, msg); doReturn(errorResponseInfoMock).when(riposteErrorHandlerMock).maybeHandleError(cause, requestInfoMock); // when ResponseInfo<ErrorResponseBody> response = handlerSpy.processError(stateMock, msg, cause); // then verify(handlerSpy).getRequestInfo(stateMock, msg); verify(riposteErrorHandlerMock).maybeHandleError(cause, requestInfoMock); ArgumentCaptor<ResponseInfo> responseInfoArgumentCaptor = ArgumentCaptor.forClass(ResponseInfo.class); verify(handlerSpy).setupResponseInfoBasedOnErrorResponseInfo(responseInfoArgumentCaptor.capture(), eq(errorResponseInfoMock)); ResponseInfo<ErrorResponseBody> responseInfoPassedIntoSetupMethod = responseInfoArgumentCaptor.getValue(); assertThat(response, is(responseInfoPassedIntoSetupMethod)); }