### Question:
ExceptionUtil { @SuppressWarnings("unchecked") public static <T extends Throwable> Optional<T> getCause( final Throwable err, Class<T> targetType) { return ExceptionUtils.getThrowableList(err).stream() .filter(targetType::isInstance) .map(e -> (T) e) .findFirst(); }  @SuppressWarnings("unchecked") static Optional<T> getCause(
      final Throwable err, Class<T> targetType);  }### Answer:
@Test public void getCause_noChainOfCauses() { final RuntimeException err = new RuntimeException(); assertThat(ExceptionUtil.getCause(err, RuntimeException.class)).contains(err); assertThat(ExceptionUtil.getCause(err, Exception.class)).contains(err); assertThat(ExceptionUtil.getCause(err, CustomRuntimeException.class)).isEmpty(); assertThat(ExceptionUtil.getCause(err, IllegalStateException.class)).isEmpty(); }
@Test public void getCause_withChainOfCauses() { final IllegalArgumentException rootCause = new IllegalArgumentException("Wrong argument"); final IllegalStateException intermediateCause = new IllegalStateException(rootCause); final RuntimeException err = new RuntimeException(intermediateCause); assertThat(ExceptionUtil.getCause(err, RuntimeException.class)).contains(err); assertThat(ExceptionUtil.getCause(err, Exception.class)).contains(err); assertThat(ExceptionUtil.getCause(err, IllegalStateException.class)) .contains(intermediateCause); assertThat(ExceptionUtil.getCause(err, IllegalArgumentException.class)).contains(rootCause); }
@Test public void getCause_withChainOfSameType() { final RuntimeException rootCause = new RuntimeException("Oops"); final RuntimeException err = new RuntimeException(rootCause); assertThat(ExceptionUtil.getCause(err, RuntimeException.class)).contains(err); }