@SuppressWarnings("unchecked")
@Test
public void testOnErrorWithFiltersExceptionFromFirstFilterSecondFilterHandles() throws Exception
{
// App stuff.
RestLiServiceException exFromApp = new RestLiServiceException(HttpStatus.S_404_NOT_FOUND, "App failure");
RequestExecutionReport executionReport = new RequestExecutionReportBuilder().build();
ErrorResponse appErrorResponse = new ErrorResponse().setStatus(404);
AugmentedRestLiResponseData responseAppData =
new AugmentedRestLiResponseData.Builder(ResourceMethod.GET).status(HttpStatus.S_404_NOT_FOUND)
.errorResponse(appErrorResponse).build();
// Filter stuff.
final Exception exFromFirstFilter = new RuntimeException("Runtime exception from first filter");
ErrorResponse filterErrorResponse = new ErrorResponse().setStatus(500);
AugmentedRestLiResponseData responseFilterData =
new AugmentedRestLiResponseData.Builder(ResourceMethod.GET).status(HttpStatus.S_500_INTERNAL_SERVER_ERROR)
.errorResponse(filterErrorResponse).build();
final RecordTemplate entityFromFilter2 = Foo.createFoo("Key", "Two");
PartialRestResponse partialResponse = new PartialRestResponse.Builder().build();
ArgumentCaptor<RestLiServiceException> wrappedExCapture = ArgumentCaptor.forClass(RestLiServiceException.class);
RestResponse restResponse = new RestResponseBuilder().build();
// Setup.
when(
_responseHandler.buildErrorResponseData(eq(_restRequest), eq(_routingResult),
wrappedExCapture.capture(), anyMap())).thenReturn(responseAppData)
.thenReturn(responseFilterData);
when(_responseHandler.buildPartialResponse(_routingResult, responseFilterData)).thenReturn(partialResponse);
when(_responseHandler.buildResponse(_routingResult, partialResponse)).thenReturn(restResponse);
when(_restRequest.getHeaders()).thenReturn(null);
// Mock filter behavior.
doThrow(exFromFirstFilter).doAnswer(new Answer<Object>()
{
@Override
public Object answer(InvocationOnMock invocation) throws Throwable
{
Object[] args = invocation.getArguments();
FilterResponseContext context = (FilterResponseContext) args[1];
// The second filter should be invoked with details of the exception thrown by the first
// filter. Verify incoming data.
assertEquals(context.getHttpStatus(), HttpStatus.S_500_INTERNAL_SERVER_ERROR);
assertNull(context.getResponseData().getEntityResponse());
assertTrue(context.getResponseHeaders().isEmpty());
assertTrue(context.getResponseData().isErrorResponse());
// Modify data.
context.setHttpStatus(HttpStatus.S_402_PAYMENT_REQUIRED);
// The second filter does handles the exception thrown by the first filter (i.e.) clears the
// error response corresponding to the exception from the first
// filter.
context.getResponseData().setEntityResponse(entityFromFilter2);
return null;
}
}).when(_filter).onResponse(eq(_filterRequestContext), any(FilterResponseContext.class));
// Invoke.
_twoFilterRestLiCallback.onError(exFromApp, executionReport);
// Verify.
verify(_responseHandler, times(2)).buildErrorResponseData(eq(_restRequest), eq(_routingResult),
wrappedExCapture.capture(), anyMap());
verify(_responseHandler).buildPartialResponse(_routingResult, responseFilterData);
verify(_responseHandler).buildResponse(_routingResult, partialResponse);
verify(_callback).onSuccess(restResponse, executionReport);
verify(_restRequest, times(2)).getHeaders();
verifyZeroInteractions(_routingResult);
verifyNoMoreInteractions(_restRequest, _responseHandler, _callback);
assertNotNull(responseFilterData);
assertEquals(HttpStatus.S_402_PAYMENT_REQUIRED, responseFilterData.getStatus());
assertTrue(responseFilterData.getHeaders().isEmpty());
assertEquals(responseFilterData.getEntityResponse(), entityFromFilter2);
assertFalse(responseFilterData.isErrorResponse());
RestLiServiceException restliEx = wrappedExCapture.getAllValues().get(0);
assertNotNull(restliEx);
assertEquals(exFromApp.getStatus(), restliEx.getStatus());
assertEquals(exFromApp.getMessage(), restliEx.getMessage());
restliEx = wrappedExCapture.getAllValues().get(1);
assertNotNull(restliEx);
assertEquals(HttpStatus.S_500_INTERNAL_SERVER_ERROR, restliEx.getStatus());
assertEquals(exFromFirstFilter.getMessage(), restliEx.getMessage());
assertEquals(exFromFirstFilter, restliEx.getCause());
}