diff --git a/src/main/java/com/github/raychatter/AnnotationHandler.java b/src/main/java/com/github/raychatter/AnnotationHandler.java index 5d116f8..8613d3e 100644 --- a/src/main/java/com/github/raychatter/AnnotationHandler.java +++ b/src/main/java/com/github/raychatter/AnnotationHandler.java @@ -20,13 +20,13 @@ public class AnnotationHandler implements HandlerExceptionResolver { private static final String UTF_8 = "UTF-8"; //TODO: When there's a wrapper exception leave it unannotated… call the e.getCause() method… until there is an annotated exception or if there are no more causes (e.geCause()==null)?? - /* [ ] If the exception thrown is annotated, use the message from that - * [x] If it is not annotated, call getCause() until you reach the innermost annotated exception. Use that message. + /* [x] If the exception thrown is annotated, use the message from that + * [x] If it is not annotated, call getCause() until you reach an annotated exception. Use that message. * [ ] If getCause()==null, return the default message and response code */ @Override public ModelAndView resolveException(final HttpServletRequest request, final HttpServletResponse response, final Object handler, final Exception thrownException) { - Exception rootException = getRootException(thrownException, thrownException.getCause()); + Exception rootException = getAnnotatedException(thrownException, thrownException.getCause()); final ExceptionHandler annotation = getAnnotationFrom(rootException); try { @@ -65,11 +65,11 @@ public class AnnotationHandler implements HandlerExceptionResolver { return new ModelAndView(); } - protected Exception getRootException(Exception thrownException, Throwable causedException) { - if(causedException == null || getAnnotationFrom((Exception)causedException)==null) { + protected Exception getAnnotatedException(Exception thrownException, Throwable causedException) { + if(getAnnotationFrom(thrownException) != null || causedException == null) { return thrownException; } else { - return getRootException((Exception) causedException, causedException.getCause()); + return getAnnotatedException((Exception) causedException, causedException.getCause()); } } diff --git a/src/test/java/com/github/raychatter/AnnotationHandlerTest.java b/src/test/java/com/github/raychatter/AnnotationHandlerTest.java index 7d840af..75ad37a 100644 --- a/src/test/java/com/github/raychatter/AnnotationHandlerTest.java +++ b/src/test/java/com/github/raychatter/AnnotationHandlerTest.java @@ -239,7 +239,7 @@ public class AnnotationHandlerTest { final AnnotationHandler sut = spy(new AnnotationHandler()); doReturn(new ModelAndView()).when(sut).handleException(mockAnnotation, expectedException, mockResponse); - doReturn(expectedException).when(sut).getRootException(expectedException, expectedException.getCause()); + doReturn(expectedException).when(sut).getAnnotatedException(expectedException, expectedException.getCause()); doReturn(mockAnnotation).when(sut).getAnnotationFrom(expectedException); final ModelAndView view = sut.resolveException(null, mockResponse, null, expectedException); @@ -255,7 +255,7 @@ public class AnnotationHandlerTest { when(mockResponse.getWriter()).thenReturn(mockPrinter); final AnnotationHandler sut = spy(new AnnotationHandler()); - when(sut.getRootException(expectedException, expectedException.getCause())).thenReturn(expectedException); + when(sut.getAnnotatedException(expectedException, expectedException.getCause())).thenReturn(expectedException); when(sut.getAnnotationFrom(expectedException)).thenReturn(null); final ModelAndView view = sut.resolveException(null, mockResponse, null, expectedException); @@ -263,27 +263,37 @@ public class AnnotationHandlerTest { verify(sut).respondWithDefault(expectedException, mockResponse); } - // TODO: Mock the getCause() method to return TestExceptionWithNoAnnotation - // Instead of the actual exception, use the getCause() mocked one - // To pass into the annotationHandler method - // Check that the response is the correct message - @Test public void resolveException_ShouldReturnRootCheckedExceptionErrorMessage_WhenThereAreCheckedExceptionsChained() throws Exception { + @Test public void getAnnotatedException_ShouldReturnOutermostAnnotatedException_WhenThereAreCheckedExceptionsChained() throws Exception { TestExceptionWithNoAnnotationAttributes mockException = mock(TestExceptionWithNoAnnotationAttributes.class); - TestExceptionWithNoContentStatusCodeAndTextContentType mockCauseException = mock(TestExceptionWithNoContentStatusCodeAndTextContentType.class); - doReturn(mockCauseException).when(mockException).getCause(); - doReturn(new TestExceptionWithNoAnnotation("")).when(mockCauseException).getCause(); + doReturn(new TestExceptionWithXmlContentType()).when(mockException).getCause(); final ExceptionHandler mockAnnotation = mock(ExceptionHandler.class); final HttpServletResponse mockResponse = mock(HttpServletResponse.class); final AnnotationHandler sut = spy(new AnnotationHandler()); - when(sut.getAnnotationFrom(mockCauseException)).thenReturn(mockAnnotation); - when(sut.getRootException(mockException, mockException.getCause())).thenReturn(mockCauseException); - doReturn(new ModelAndView()).when(sut).handleException(mockAnnotation, mockCauseException, mockResponse); + when(sut.getAnnotationFrom(mockException)).thenReturn(mockAnnotation); + doReturn(new ModelAndView()).when(sut).handleException(mockAnnotation, mockException, mockResponse); final ModelAndView view = sut.resolveException(null, mockResponse, null, mockException); - verify(sut).handleException(mockAnnotation, mockCauseException, mockResponse); //TestExceptionWithNoContentStatusCodeAndTextContentType + Assert.assertTrue(sut.getAnnotatedException(mockException,mockException.getCause()) instanceof TestExceptionWithNoAnnotationAttributes); + } + + @Test public void getAnnotatedException_ShouldReturnFirstChainedAnnotatedException_WhenThrownExceptionIsUnannotated() throws Exception { + TestExceptionWithNoAnnotation mockException = mock(TestExceptionWithNoAnnotation.class); + TestExceptionWithNoAnnotationAttributes expectedException = new TestExceptionWithNoAnnotationAttributes(""); + doReturn(expectedException).when(mockException).getCause(); + + final ExceptionHandler mockAnnotation = mock(ExceptionHandler.class); + final HttpServletResponse mockResponse = mock(HttpServletResponse.class); + + final AnnotationHandler sut = spy(new AnnotationHandler()); + when(sut.getAnnotationFrom(expectedException)).thenReturn(mockAnnotation); + doReturn(new ModelAndView()).when(sut).handleException(mockAnnotation, expectedException, mockResponse); + + final ModelAndView view = sut.resolveException(null, mockResponse, null, expectedException); + + Assert.assertTrue(sut.getAnnotatedException(mockException,mockException.getCause()) instanceof TestExceptionWithNoAnnotationAttributes); } } @@ -307,10 +317,6 @@ class TestExceptionWithNoContentStatusCodeAndTextContentType extends Exception { public TestExceptionWithNoContentStatusCodeAndTextContentType(final String s) { super(s); } - - public TestExceptionWithNoContentStatusCodeAndTextContentType(final String s, Throwable ex) { - super(s,ex); - } } class TestExceptionWithNoAnnotation extends Exception {