### Question:
ExceptionTransformer { public Exception transformException(Exception exception) { logger.entry(exception); if (exception.getCause() == null) { if (exception.getClass() == this.clazzCause) { return wrapThrowable(exception); } else { return exception; } } int indexOfCause = ExceptionUtils.indexOfThrowable(exception, this.clazzCause); if (indexOfCause != -1) { if (this.clazzSubCause != null) { if (ExceptionUtils.indexOfThrowable(exception, this.clazzSubCause, indexOfCause) != -1) { return wrapThrowable(exception); } else { return exception; } } else { return wrapThrowable(exception); } } else { return exception; } } ExceptionTransformer(Class<? extends T> clazzT,
                                Class<? extends Throwable> clazzCause,
                                Class<? extends Throwable> clazzSubCause);  ExceptionTransformer(Class<? extends T> clazzT,
                                Class<? extends Throwable> clazzCause); Throwable transformThrowable(Throwable throwable); Exception transformException(Exception exception); boolean causeInChain(Throwable throwable, Class<? extends Throwable> clazz); boolean causesInChain(Throwable throwable); boolean causesInChain(Throwable throwable, Class<? extends Throwable> clazz, Class<? extends Throwable> subClazz); Class<? extends T> getClassT(); Class<? extends Throwable> getClassCause(); Class<? extends Throwable> getClassSubCause();  }### Answer:
@Test(expected = IllegalStateException.class) public void testBadRuntimeException() { ExceptionTransformer<BadRuntimeException> exceptionTransformer = new ExceptionTransformer<>( BadRuntimeException.class, SQLException.class); SQLException s = new SQLException("My custom SQL Exception"); Throwable actual = exceptionTransformer.transformException(s); assertThat(actual).hasCause(new SQLException()); }
@Test public void testCatchSqlException() { ExceptionTransformer<CustomRuntimeException> exceptionTransformer = new ExceptionTransformer<>( CustomRuntimeException.class, SQLException.class); SQLException sqlException = new SQLException("My custom SQL Exception"); Throwable actual = exceptionTransformer.transformException(sqlException); assertThat(actual).isInstanceOf(CustomRuntimeException.class); assertThat(actual).hasCause(sqlException); }
@Test public void testCatchValidSqlExceptionWithCause() { ExceptionTransformer<CustomRuntimeException> exceptionTransformer = new ExceptionTransformer<>( CustomRuntimeException.class, SQLException.class, SocketException.class); SocketException socketException = new SocketException("My custom SocketException"); SQLException sqlException = new SQLException("My custom SQL Exception", socketException); Throwable actual = exceptionTransformer.transformException(sqlException); assertThat(actual).isInstanceOf(CustomRuntimeException.class); assertThat(actual).hasCause(sqlException); assertThat(ExceptionUtils.indexOfThrowable(actual, socketException.getClass())).isNotNegative(); }
@Test public void testCatchInvalidSqlExceptionWithCause() { ExceptionTransformer<CustomRuntimeException> exceptionNotFoundTransformer = new ExceptionTransformer<>( CustomRuntimeException.class, BadRuntimeException.class, SocketException.class); SocketException socketException = new SocketException("My custom SocketException"); SQLException sqlException = new SQLException("My custom SQL Exception", socketException); Throwable actual = exceptionNotFoundTransformer.transformException(sqlException); assertThat(actual).isNotInstanceOf(CustomRuntimeException.class); exceptionNotFoundTransformer = new ExceptionTransformer<>( CustomRuntimeException.class, SQLException.class, BadRuntimeException.class); actual = exceptionNotFoundTransformer.transformException(sqlException); assertThat(actual).isNotInstanceOf(CustomRuntimeException.class); }