Repository: assertj/assertj

Problem statement:
`catchThrowableOfType` enriched alternatives
#### Summary
Similarly to the enriched alternatives of [`assertThatExceptionOfType`](https://assertj.github.io/doc/#assertj-core-exception-assertions-assertThatExceptionOfType), we could introduce enriched versions of `catchThrowableOfType`.

#### Example

```java
NullPointerException npe = catchNullPointerException( () -> ... );
IllegalArgumentException iae = catchIllegalArgumentException( () -> ... );
IllegalStateException ise = catchIllegalStateException( () -> ... );
IOException ioe = catchIOException( () -> ... );
```



Hints:
I would like to work on this one as my first contribution
Sure, thanks @Spacca!

Patch:
diff --git a/src/main/java/org/assertj/core/api/Assertions.java b/src/main/java/org/assertj/core/api/Assertions.java
--- a/src/main/java/org/assertj/core/api/Assertions.java
+++ b/src/main/java/org/assertj/core/api/Assertions.java
@@ -1160,7 +1160,7 @@ public static <T extends Throwable> AbstractThrowableAssert<?, T> assertThat(T a
    *
    * If the provided {@link ThrowingCallable} does not raise an exception, an error is immediately thrown,
    * in that case the test description provided with {@link AbstractAssert#as(String, Object...) as(String, Object...)} is not honored.<br>
-   * To use a test description, use {@link #catchThrowable(ThrowableAssert.ThrowingCallable)} as shown below:
+   * To use a test description, use {@link #catchThrowable(ThrowingCallable)} as shown below:
    * <pre><code class='java'> // assertion will fail but "display me" won't appear in the error
    * assertThatThrownBy(() -&gt; {}).as("display me")
    *                             .isInstanceOf(Exception.class);
@@ -1316,7 +1316,7 @@ public static <T> ObjectAssert<T> assertWith(T actual, Consumer<T>... requiremen
    * <p>
    * This caught {@link Throwable} can then be asserted.
    * <p>
-   * If you need to assert on the real type of Throwable caught (e.g. IOException), use {@link #catchThrowableOfType(ThrowableAssert.ThrowingCallable, Class)}.
+   * If you need to assert on the real type of Throwable caught (e.g. IOException), use {@link #catchThrowableOfType(ThrowingCallable, Class)}.
    * <p>
    * Example:
    * <pre><code class='java'>{@literal @}Test
@@ -1331,7 +1331,7 @@ public static <T> ObjectAssert<T> assertWith(T actual, Consumer<T>... requiremen
    *
    * @param shouldRaiseThrowable The lambda with the code that should raise the exception.
    * @return The captured exception or <code>null</code> if none was raised by the callable.
-   * @see #catchThrowableOfType(ThrowableAssert.ThrowingCallable, Class)
+   * @see #catchThrowableOfType(ThrowingCallable, Class)
    */
   public static Throwable catchThrowable(ThrowingCallable shouldRaiseThrowable) {
     return AssertionsForClassTypes.catchThrowable(shouldRaiseThrowable);
@@ -1372,7 +1372,7 @@ public static Throwable catchThrowable(ThrowingCallable shouldRaiseThrowable) {
    * @param shouldRaiseThrowable The lambda with the code that should raise the exception.
    * @param type The type of exception that the code is expected to raise.
    * @return The captured exception or <code>null</code> if none was raised by the callable.
-   * @see #catchThrowable(ThrowableAssert.ThrowingCallable)
+   * @see #catchThrowable(ThrowingCallable)
    * @since 3.9.0
    */
   public static <THROWABLE extends Throwable> THROWABLE catchThrowableOfType(ThrowingCallable shouldRaiseThrowable,
@@ -1380,6 +1380,222 @@ public static <THROWABLE extends Throwable> THROWABLE catchThrowableOfType(Throw
     return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseThrowable, type);
   }
 
+  /**
+   * Allows catching an instance of {@link Exception}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link Exception} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * Exception exception = catchException(() -&gt; {throw new Exception("boom!");});
+   * // assertions succeed
+   * assertThat(exception).hasMessage("boom!");
+   *
+   * // succeeds as catchException returns null when the code does not throw any exceptions
+   * assertThat(catchException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not an Exception
+   * catchException(() -&gt; {throw new Throwable("boom!");});</code></pre>
+   *
+   * @param shouldRaiseException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  public static Exception catchException(ThrowingCallable shouldRaiseException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseException, Exception.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link RuntimeException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link RuntimeException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * RuntimeException runtimeException = catchRuntimeException(() -&gt; {throw new RuntimeException("boom!");});
+   * // assertions succeed
+   * assertThat(runtimeException).hasMessage("boom!");
+   *
+   * // succeeds as catchRuntimeException returns null when the code does not throw any exceptions
+   * assertThat(catchRuntimeException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not a RuntimeException
+   * catchRuntimeException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseRuntimeException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  public static RuntimeException catchRuntimeException(ThrowingCallable shouldRaiseRuntimeException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseRuntimeException, RuntimeException.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link NullPointerException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link RuntimeException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * NullPointerException nullPointerException = catchNullPointerException(() -&gt; {throw new NullPointerException("boom!");});
+   * // assertions succeed
+   * assertThat(nullPointerException).hasMessage("boom!");
+   *
+   * // succeeds as catchNullPointerException returns null when the code does not throw any exceptions
+   * assertThat(catchNullPointerException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not a NullPointerException
+   * catchNullPointerException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseNullPointerException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  public static NullPointerException catchNullPointerException(ThrowingCallable shouldRaiseNullPointerException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseNullPointerException, NullPointerException.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link IllegalArgumentException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link IllegalArgumentException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * IllegalArgumentException illegalArgumentException = catchIllegalArgumentException(() -&gt; {throw new IllegalArgumentException("boom!");});
+   * // assertions succeed
+   * assertThat(illegalArgumentException).hasMessage("boom!");
+   *
+   * // succeeds as catchNullPointerException returns null when the code does not throw any exceptions
+   * assertThat(catchIllegalArgumentException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not an IllegalArgumentException
+   * catchIllegalArgumentException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseIllegalArgumentException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  public static IllegalArgumentException catchIllegalArgumentException(ThrowingCallable shouldRaiseIllegalArgumentException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseIllegalArgumentException, IllegalArgumentException.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link IOException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link IOException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * IOException iOException = catchIOException(() -&gt; {throw new IOException("boom!");});
+   * // assertions succeed
+   * assertThat(iOException).hasMessage("boom!");
+   *
+   * // succeeds as catchIOException returns null when the code does not throw any exceptions
+   * assertThat(catchIOException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not an IOException
+   * catchIOException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseIOException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  public static IOException catchIOException(ThrowingCallable shouldRaiseIOException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseIOException, IOException.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link ReflectiveOperationException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link ReflectiveOperationException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * ReflectiveOperationException reflectiveOperationException = catchReflectiveOperationException(() -&gt; {throw new ReflectiveOperationException("boom!");});
+   * // assertions succeed
+   * assertThat(reflectiveOperationException).hasMessage("boom!");
+   *
+   * // succeeds as catchReflectiveOperationException returns null when the code does not throw any exceptions
+   * assertThat(catchReflectiveOperationException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not an IOException
+   * catchReflectiveOperationException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseReflectiveOperationException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  public static ReflectiveOperationException catchReflectiveOperationException(ThrowingCallable shouldRaiseReflectiveOperationException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseReflectiveOperationException, ReflectiveOperationException.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link IllegalStateException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link IllegalStateException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * IllegalStateException illegalStateException = catchIllegalStateException(() -&gt; {throw new IllegalStateException("boom!");});
+   * // assertions succeed
+   * assertThat(illegalStateException).hasMessage("boom!");
+   *
+   * // succeeds as catchReflectiveOperationException returns null when the code does not throw any exceptions
+   * assertThat(catchIllegalStateException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not an IOException
+   * catchIllegalStateException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseIllegalStateException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  public static IllegalStateException catchIllegalStateException(ThrowingCallable shouldRaiseIllegalStateException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseIllegalStateException, IllegalStateException.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link IndexOutOfBoundsException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link IndexOutOfBoundsException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * IndexOutOfBoundsException indexOutOfBoundsException = catchIndexOutOfBoundsException(() -&gt; {throw new IndexOutOfBoundsException("boom!");});
+   * // assertions succeed
+   * assertThat(indexOutOfBoundsException).hasMessage("boom!");
+   *
+   * // succeeds as catchIndexOutOfBoundsException returns null when the code does not throw any exceptions
+   * assertThat(catchIndexOutOfBoundsException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not an IOException
+   * catchIndexOutOfBoundsException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseIndexOutOfBoundException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  public static IndexOutOfBoundsException catchIndexOutOfBoundsException(ThrowingCallable shouldRaiseIndexOutOfBoundException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseIndexOutOfBoundException, IndexOutOfBoundsException.class);
+  }
+
   /**
    * Entry point to check that an exception of type T is thrown by a given {@code throwingCallable}
    * which allows to chain assertions on the thrown exception.
@@ -1389,7 +1605,7 @@ public static <THROWABLE extends Throwable> THROWABLE catchThrowableOfType(Throw
    *           .isThrownBy(() -&gt; { throw new IOException("boom!"); })
    *           .withMessage("boom!"); </code></pre>
    *
-   * This method is more or less the same of {@link #assertThatThrownBy(ThrowableAssert.ThrowingCallable)} but in a more natural way.
+   * This method is more or less the same of {@link #assertThatThrownBy(ThrowingCallable)} but in a more natural way.
    *
    * @param <T> the exception type.
    * @param exceptionType the exception type class.
diff --git a/src/main/java/org/assertj/core/api/BDDAssertions.java b/src/main/java/org/assertj/core/api/BDDAssertions.java
--- a/src/main/java/org/assertj/core/api/BDDAssertions.java
+++ b/src/main/java/org/assertj/core/api/BDDAssertions.java
@@ -1178,7 +1178,7 @@ public static <T extends Throwable> AbstractThrowableAssert<?, T> then(T actual)
    *
    * If the provided {@link ThrowingCallable} does not raise an exception, an error is immediately thrown,
    * in that case the test description provided with {@link AbstractAssert#as(String, Object...) as(String, Object...)} is not honored.<br>
-   * To use a test description, use {@link #catchThrowable(ThrowableAssert.ThrowingCallable)} as shown below:
+   * To use a test description, use {@link #catchThrowable(ThrowingCallable)} as shown below:
    * <pre><code class='java'> // assertion will fail but "display me" won't appear in the error
    * thenThrownBy(() -&gt; {}).as("display me")
    *                       .isInstanceOf(Exception.class);
@@ -1256,7 +1256,7 @@ public static <T extends Throwable> AbstractThrowableAssert<?, T> then(T actual)
    *
    * If the provided {@link ThrowingCallable} does not validate against next assertions, an error is immediately raised,
    * in that case the test description provided with {@link AbstractAssert#as(String, Object...) as(String, Object...)} is not honored.<br>
-   * To use a test description, use {@link #catchThrowable(ThrowableAssert.ThrowingCallable)} as shown below.
+   * To use a test description, use {@link #catchThrowable(ThrowingCallable)} as shown below.
    *
    * <pre><code class='java'> ThrowingCallable doNothing = () -&gt; {
    *   // do nothing
@@ -1680,7 +1680,7 @@ public static <ELEMENT> SpliteratorAssert<ELEMENT> then(Spliterator<ELEMENT> act
    * <p>
    * This caught {@link Throwable} can then be asserted.
    * <p>
-   * If you need to assert on the real type of Throwable caught (e.g. IOException), use {@link #catchThrowableOfType(ThrowableAssert.ThrowingCallable, Class)}.
+   * If you need to assert on the real type of Throwable caught (e.g. IOException), use {@link #catchThrowableOfType(ThrowingCallable, Class)}.
    * <p>
    * Example:
    * <pre><code class='java'>{@literal @}Test
@@ -1695,7 +1695,7 @@ public static <ELEMENT> SpliteratorAssert<ELEMENT> then(Spliterator<ELEMENT> act
    *
    * @param shouldRaiseThrowable The lambda with the code that should raise the exception.
    * @return The captured exception or <code>null</code> if none was raised by the callable.
-   * @see #catchThrowableOfType(ThrowableAssert.ThrowingCallable, Class)
+   * @see #catchThrowableOfType(ThrowingCallable, Class)
    *
    * @since 3.20.0
    */
@@ -1738,7 +1738,7 @@ public static Throwable catchThrowable(ThrowingCallable shouldRaiseThrowable) {
    * @param shouldRaiseThrowable The lambda with the code that should raise the exception.
    * @param type The type of exception that the code is expected to raise.
    * @return The captured exception or <code>null</code> if none was raised by the callable.
-   * @see #catchThrowable(ThrowableAssert.ThrowingCallable)
+   * @see #catchThrowable(ThrowingCallable)
    *
    * @since 3.20.0
    */
@@ -1747,6 +1747,222 @@ public static <THROWABLE extends Throwable> THROWABLE catchThrowableOfType(Throw
     return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseThrowable, type);
   }
 
+  /**
+   * Allows catching an instance of {@link Exception}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link Exception} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * Exception exception = catchException(() -&gt; {throw new Exception("boom!");});
+   * // assertions succeed
+   * assertThat(exception).hasMessage("boom!");
+   *
+   * // succeeds as catchException returns null when the code does not throw any exceptions
+   * assertThat(catchException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not an Exception
+   * catchException(() -&gt; {throw new Throwable("boom!");});</code></pre>
+   *
+   * @param shouldRaiseException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  public static Exception catchException(ThrowingCallable shouldRaiseException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseException, Exception.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link RuntimeException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link RuntimeException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * RuntimeException runtimeException = catchRuntimeException(() -&gt; {throw new RuntimeException("boom!");});
+   * // assertions succeed
+   * assertThat(runtimeException).hasMessage("boom!");
+   *
+   * // succeeds as catchRuntimeException returns null when the code does not throw any exceptions
+   * assertThat(catchRuntimeException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not a RuntimeException
+   * catchRuntimeException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseRuntimeException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  public static RuntimeException catchRuntimeException(ThrowingCallable shouldRaiseRuntimeException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseRuntimeException, RuntimeException.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link NullPointerException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link RuntimeException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * NullPointerException nullPointerException = catchNullPointerException(() -&gt; {throw new NullPointerException("boom!");});
+   * // assertions succeed
+   * assertThat(nullPointerException).hasMessage("boom!");
+   *
+   * // succeeds as catchNullPointerException returns null when the code does not throw any exceptions
+   * assertThat(catchNullPointerException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not a NullPointerException
+   * catchNullPointerException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseNullPointerException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  public static NullPointerException catchNullPointerException(ThrowingCallable shouldRaiseNullPointerException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseNullPointerException, NullPointerException.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link IllegalArgumentException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link IllegalArgumentException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * IllegalArgumentException illegalArgumentException = catchIllegalArgumentException(() -&gt; {throw new IllegalArgumentException("boom!");});
+   * // assertions succeed
+   * assertThat(illegalArgumentException).hasMessage("boom!");
+   *
+   * // succeeds as catchNullPointerException returns null when the code does not throw any exceptions
+   * assertThat(catchIllegalArgumentException(() -&gt; {})).isNull();</code></pre>
+   *
+   * // fails as the thrown instance is not an IllegalArgumentException
+   * catchIllegalArgumentException(() -&gt; {throw new Exception("boom!");});
+   *
+   * @param shouldRaiseIllegalArgumentException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  public static IllegalArgumentException catchIllegalArgumentException(ThrowingCallable shouldRaiseIllegalArgumentException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseIllegalArgumentException, IllegalArgumentException.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link IOException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link IOException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * IOException iOException = catchIOException(() -&gt; {throw new IOException("boom!");});
+   * // assertions succeed
+   * assertThat(iOException).hasMessage("boom!");
+   *
+   * // succeeds as catchIOException returns null when the code does not throw any exceptions
+   * assertThat(catchIOException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not an IOException
+   * catchIOException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseIOException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  public static IOException catchIOException(ThrowingCallable shouldRaiseIOException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseIOException, IOException.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link ReflectiveOperationException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link ReflectiveOperationException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * ReflectiveOperationException reflectiveOperationException = catchReflectiveOperationException(() -&gt; {throw new ReflectiveOperationException("boom!");});
+   * // assertions succeed
+   * assertThat(reflectiveOperationException).hasMessage("boom!");
+   *
+   * // succeeds as catchReflectiveOperationException returns null when the code does not throw any exceptions
+   * assertThat(catchReflectiveOperationException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not an IOException
+   * catchReflectiveOperationException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseReflectiveOperationException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  public static ReflectiveOperationException catchReflectiveOperationException(ThrowingCallable shouldRaiseReflectiveOperationException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseReflectiveOperationException, ReflectiveOperationException.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link IllegalStateException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link IllegalStateException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * IllegalStateException illegalStateException = catchIllegalStateException(() -&gt; {throw new IllegalStateException("boom!");});
+   * // assertions succeed
+   * assertThat(illegalStateException).hasMessage("boom!");
+   *
+   * // succeeds as catchReflectiveOperationException returns null when the code does not throw any exceptions
+   * assertThat(catchIllegalStateException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not an IOException
+   * catchIllegalStateException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseIllegalStateException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  public static IllegalStateException catchIllegalStateException(ThrowingCallable shouldRaiseIllegalStateException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseIllegalStateException, IllegalStateException.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link IndexOutOfBoundsException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link IndexOutOfBoundsException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * IndexOutOfBoundsException indexOutOfBoundsException = catchIndexOutOfBoundsException(() -&gt; {throw new IndexOutOfBoundsException("boom!");});
+   * // assertions succeed
+   * assertThat(indexOutOfBoundsException).hasMessage("boom!");
+   *
+   * // succeeds as catchIndexOutOfBoundsException returns null when the code does not throw any exceptions
+   * assertThat(catchIndexOutOfBoundsException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not an IOException
+   * catchIndexOutOfBoundsException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseIndexOutOfBoundException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  public static IndexOutOfBoundsException catchIndexOutOfBoundsException(ThrowingCallable shouldRaiseIndexOutOfBoundException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseIndexOutOfBoundException, IndexOutOfBoundsException.class);
+  }
+
   /**
    * Entry point to check that an exception of type T is thrown by a given {@code throwingCallable}
    * which allows to chain assertions on the thrown exception.
@@ -1756,7 +1972,7 @@ public static <THROWABLE extends Throwable> THROWABLE catchThrowableOfType(Throw
    *           .isThrownBy(() -&gt; { throw new IOException("boom!"); })
    *           .withMessage("boom!"); </code></pre>
    *
-   * This method is more or less the same of {@link #thenThrownBy(ThrowableAssert.ThrowingCallable)} but in a more natural way.
+   * This method is more or less the same of {@link #thenThrownBy(ThrowingCallable)} but in a more natural way.
    *
    * @param <T> the exception type.
    * @param exceptionType the exception type class.
diff --git a/src/main/java/org/assertj/core/api/WithAssertions.java b/src/main/java/org/assertj/core/api/WithAssertions.java
--- a/src/main/java/org/assertj/core/api/WithAssertions.java
+++ b/src/main/java/org/assertj/core/api/WithAssertions.java
@@ -2458,7 +2458,7 @@ default AbstractOffsetDateTimeAssert<?> assertThat(final OffsetDateTime offsetDa
    *
    * If the provided {@link ThrowingCallable} does not raise an exception, an error is immediately thrown,
    * in that case the test description provided with {@link AbstractAssert#as(String, Object...) as(String, Object...)} is not honored.<br>
-   * To use a test description, use {@link #catchThrowable(ThrowableAssert.ThrowingCallable)} as shown below:
+   * To use a test description, use {@link #catchThrowable(ThrowingCallable)} as shown below:
    * <pre><code class='java'> // assertion will fail but "display me" won't appear in the error
    * assertThatThrownBy(() -&gt; {}).as("display me")
    *                             .isInstanceOf(Exception.class);
@@ -2537,7 +2537,7 @@ default AbstractOffsetDateTimeAssert<?> assertThat(final OffsetDateTime offsetDa
    *
    * If the provided {@link ThrowingCallable} does not validate against next assertions, an error is immediately raised,
    * in that case the test description provided with {@link AbstractAssert#as(String, Object...) as(String, Object...)} is not honored.<br>
-   * To use a test description, use {@link #catchThrowable(ThrowableAssert.ThrowingCallable)} as shown below.
+   * To use a test description, use {@link #catchThrowable(ThrowingCallable)} as shown below.
    *
    * <pre><code class='java'> ThrowingCallable doNothing = () -&gt; {
    *   // do nothing
@@ -2636,7 +2636,7 @@ default <T> ObjectAssert<T> assertWith(T actual, @SuppressWarnings("unchecked")
    *
    * @param shouldRaiseThrowable The lambda with the code that should raise the exception.
    * @return The captured exception or <code>null</code> if none was raised by the callable.
-   * @see #catchThrowableOfType(ThrowableAssert.ThrowingCallable, Class)
+   * @see #catchThrowableOfType(ThrowingCallable, Class)
    */
   default Throwable catchThrowable(final ThrowingCallable shouldRaiseThrowable) {
     return Assertions.catchThrowable(shouldRaiseThrowable);
@@ -2676,7 +2676,7 @@ default Throwable catchThrowable(final ThrowingCallable shouldRaiseThrowable) {
    * @param shouldRaiseThrowable The lambda with the code that should raise the exception.
    * @param type The type of exception that the code is expected to raise.
    * @return The captured exception or <code>null</code> if none was raised by the callable.
-   * @see #catchThrowable(ThrowableAssert.ThrowingCallable)
+   * @see #catchThrowable(ThrowingCallable)
    * @since 3.9.0
    */
   default <THROWABLE extends Throwable> THROWABLE catchThrowableOfType(final ThrowingCallable shouldRaiseThrowable,
@@ -2684,6 +2684,222 @@ default <THROWABLE extends Throwable> THROWABLE catchThrowableOfType(final Throw
     return Assertions.catchThrowableOfType(shouldRaiseThrowable, type);
   }
 
+  /**
+   * Allows catching an instance of {@link Exception}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link Exception} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * Exception exception = catchException(() -&gt; {throw new Exception("boom!");});
+   * // assertions succeed
+   * assertThat(exception).hasMessage("boom!");
+   *
+   * // succeeds as catchException returns null when the code does not throw any exceptions
+   * assertThat(catchException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not an Exception
+   * catchException(() -&gt; {throw new Throwable("boom!");});</code></pre>
+   *
+   * @param shouldRaiseException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  default Exception catchException(ThrowingCallable shouldRaiseException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseException, Exception.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link RuntimeException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link RuntimeException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * RuntimeException runtimeException = catchRuntimeException(() -&gt; {throw new RuntimeException("boom!");});
+   * // assertions succeed
+   * assertThat(runtimeException).hasMessage("boom!");
+   *
+   * // succeeds as catchRuntimeException returns null when the code does not throw any exceptions
+   * assertThat(catchRuntimeException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not a RuntimeException
+   * catchRuntimeException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseRuntimeException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  default RuntimeException catchRuntimeException(ThrowingCallable shouldRaiseRuntimeException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseRuntimeException, RuntimeException.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link NullPointerException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link RuntimeException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * NullPointerException nullPointerException = catchNullPointerException(() -&gt; {throw new NullPointerException("boom!");});
+   * // assertions succeed
+   * assertThat(nullPointerException).hasMessage("boom!");
+   *
+   * // succeeds as catchNullPointerException returns null when the code does not throw any exceptions
+   * assertThat(catchNullPointerException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not a NullPointerException
+   * catchNullPointerException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseNullPointerException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  default NullPointerException catchNullPointerException(ThrowingCallable shouldRaiseNullPointerException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseNullPointerException, NullPointerException.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link IllegalArgumentException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link IllegalArgumentException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * IllegalArgumentException illegalArgumentException = catchIllegalArgumentException(() -&gt; {throw new IllegalArgumentException("boom!");});
+   * // assertions succeed
+   * assertThat(illegalArgumentException).hasMessage("boom!");
+   *
+   * // succeeds as catchNullPointerException returns null when the code does not throw any exceptions
+   * assertThat(catchIllegalArgumentException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not an IllegalArgumentException
+   * catchIllegalArgumentException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseIllegalArgumentException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  default IllegalArgumentException catchIllegalArgumentException(ThrowingCallable shouldRaiseIllegalArgumentException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseIllegalArgumentException, IllegalArgumentException.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link IOException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link IOException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * IOException iOException = catchIOException(() -&gt; {throw new IOException("boom!");});
+   * // assertions succeed
+   * assertThat(iOException).hasMessage("boom!");
+   *
+   * // succeeds as catchIOException returns null when the code does not throw any exceptions
+   * assertThat(catchIOException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not an IOException
+   * catchIOException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseIOException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  default IOException catchIOException(ThrowingCallable shouldRaiseIOException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseIOException, IOException.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link ReflectiveOperationException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link ReflectiveOperationException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * ReflectiveOperationException reflectiveOperationException = catchReflectiveOperationException(() -&gt; {throw new ReflectiveOperationException("boom!");});
+   * // assertions succeed
+   * assertThat(reflectiveOperationException).hasMessage("boom!");
+   *
+   * // succeeds as catchReflectiveOperationException returns null when the code does not throw any exceptions
+   * assertThat(catchReflectiveOperationException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not an IOException
+   * catchReflectiveOperationException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseReflectiveOperationException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  default ReflectiveOperationException catchReflectiveOperationException(ThrowingCallable shouldRaiseReflectiveOperationException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseReflectiveOperationException, ReflectiveOperationException.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link IllegalStateException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link IllegalStateException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * IllegalStateException illegalStateException = catchIllegalStateException(() -&gt; {throw new IllegalStateException("boom!");});
+   * // assertions succeed
+   * assertThat(illegalStateException).hasMessage("boom!");
+   *
+   * // succeeds as catchReflectiveOperationException returns null when the code does not throw any exceptions
+   * assertThat(catchIllegalStateException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not an IOException
+   * catchIllegalStateException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseIllegalStateException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  default IllegalStateException catchIllegalStateException(ThrowingCallable shouldRaiseIllegalStateException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseIllegalStateException, IllegalStateException.class);
+  }
+
+  /**
+   * Allows catching an instance of {@link IndexOutOfBoundsException}.
+   * <p>
+   * A call is made to {@code catchThrowable(ThrowingCallable)}, if no exception is thrown it returns null
+   * otherwise it checks that the caught {@link Throwable} is of type {@link IndexOutOfBoundsException} and casts it making it convenient to perform subtype-specific assertions on it.
+   * <p>
+   * Example:
+   * <pre><code class='java'>
+   * IndexOutOfBoundsException indexOutOfBoundsException = catchIndexOutOfBoundsException(() -&gt; {throw new IndexOutOfBoundsException("boom!");});
+   * // assertions succeed
+   * assertThat(indexOutOfBoundsException).hasMessage("boom!");
+   *
+   * // succeeds as catchIndexOutOfBoundsException returns null when the code does not throw any exceptions
+   * assertThat(catchIndexOutOfBoundsException(() -&gt; {})).isNull();
+   *
+   * // fails as the thrown instance is not an IOException
+   * catchIndexOutOfBoundsException(() -&gt; {throw new Exception("boom!");});</code></pre>
+   *
+   * @param shouldRaiseIndexOutOfBoundException The lambda with the code that should raise the exception.
+   * @return The captured exception or <code>null</code> if none was raised by the callable.
+   * @see #catchThrowable(ThrowingCallable)
+   * @since 3.22.0
+   */
+  default IndexOutOfBoundsException catchIndexOutOfBoundsException(ThrowingCallable shouldRaiseIndexOutOfBoundException) {
+    return AssertionsForClassTypes.catchThrowableOfType(shouldRaiseIndexOutOfBoundException, IndexOutOfBoundsException.class);
+  }
+
   /**
    * Entry point to check that an exception of type T is thrown by a given {@code throwingCallable}
    * which allows to chain assertions on the thrown exception.
@@ -2693,7 +2909,7 @@ default <THROWABLE extends Throwable> THROWABLE catchThrowableOfType(final Throw
    *           .isThrownBy(() -&gt; { throw new IOException("boom!"); })
    *           .withMessage("boom!"); </code></pre>
    *
-   * This method is more or less the same of {@link #assertThatThrownBy(ThrowableAssert.ThrowingCallable)} but in a more natural way.
+   * This method is more or less the same of {@link #assertThatThrownBy(ThrowingCallable)} but in a more natural way.
    *
    * @param <T> the exception type.
    * @param exceptionType the exception type class.


Test patch:
diff --git a/src/test/java/org/assertj/core/api/Assertions_catchException_Test.java b/src/test/java/org/assertj/core/api/Assertions_catchException_Test.java
new file mode 100644
--- /dev/null
+++ b/src/test/java/org/assertj/core/api/Assertions_catchException_Test.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2021 the original author or authors.
+ */
+package org.assertj.core.api;
+
+import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.catchException;
+import static org.assertj.core.api.Assertions_catchThrowable_Test.codeThrowing;
+import static org.assertj.core.api.BDDAssertions.then;
+import static org.assertj.core.util.AssertionsUtil.expectAssertionError;
+import static org.mockito.Mockito.mock;
+
+class Assertions_catchException_Test {
+
+  @Test
+  void catchException_should_fail_with_good_message_if_wrong_type() {
+    // GIVEN
+    ThrowingCallable code = () -> catchException(raisingThrowable("boom!!"));
+    // WHEN
+    AssertionError assertionError = expectAssertionError(code);
+    // THEN
+    assertThat(assertionError).hasMessageContainingAll(Exception.class.getName(), Throwable.class.getName());
+  }
+
+  @Test
+  void catchException_should_succeed_and_return_actual_instance_with_correct_class() {
+    // GIVEN
+    final Exception expected = new Exception("boom!!");
+    // WHEN
+    Exception actual = catchException(codeThrowing(expected));
+    // THEN
+    then(actual).isSameAs(expected);
+  }
+
+  @Test
+  void catchException_should_succeed_and_return_null_if_no_exception_thrown() {
+    // WHEN
+    Exception actual = catchException(() -> {});
+    // THEN
+    then(actual).isNull();
+  }
+
+  @Test
+  void catchException_should_catch_mocked_throwable() {
+    // GIVEN
+    Exception exception = mock(Exception.class);
+    // WHEN
+    Throwable actual = catchException(codeThrowing(exception));
+    // THEN
+    then(actual).isSameAs(exception);
+  }
+
+  static ThrowingCallable raisingThrowable(final String reason) {
+    return codeThrowing(new Throwable(reason));
+  }
+
+}
diff --git a/src/test/java/org/assertj/core/api/Assertions_catchIOException_Test.java b/src/test/java/org/assertj/core/api/Assertions_catchIOException_Test.java
new file mode 100644
--- /dev/null
+++ b/src/test/java/org/assertj/core/api/Assertions_catchIOException_Test.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2021 the original author or authors.
+ */
+package org.assertj.core.api;
+
+import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.catchIOException;
+import static org.assertj.core.api.Assertions_catchThrowable_Test.codeThrowing;
+import static org.assertj.core.api.BDDAssertions.then;
+import static org.assertj.core.util.AssertionsUtil.expectAssertionError;
+import static org.mockito.Mockito.mock;
+
+class Assertions_catchIOException_Test {
+
+  @Test
+  void catchIOException_should_fail_with_good_message_if_wrong_type() {
+    // GIVEN
+    ThrowingCallable code = () -> catchIOException(raisingException("boom!!"));
+    // WHEN
+    AssertionError assertionError = expectAssertionError(code);
+    // THEN
+    assertThat(assertionError).hasMessageContainingAll(Exception.class.getName(), IOException.class.getName());
+  }
+
+  @Test
+  void catchIOException_should_succeed_and_return_actual_instance_with_correct_class() {
+    // GIVEN
+    final IOException expected = new IOException("boom!!");
+    // WHEN
+    IOException actual = catchIOException(codeThrowing(expected));
+    // THEN
+    then(actual).isSameAs(expected);
+  }
+
+  @Test
+  void catchIOException_should_succeed_and_return_null_if_no_exception_thrown() {
+    // WHEN
+    IOException actual = catchIOException(() -> {});
+    // THEN
+    then(actual).isNull();
+  }
+
+  @Test
+  void catchIOException_should_catch_mocked_throwable() {
+    // GIVEN
+    IOException exception = mock(IOException.class);
+    // WHEN
+    Throwable actual = catchIOException(codeThrowing(exception));
+    // THEN
+    then(actual).isSameAs(exception);
+  }
+
+  static ThrowingCallable raisingException(final String reason) {
+    return codeThrowing(new Exception(reason));
+  }
+
+}
diff --git a/src/test/java/org/assertj/core/api/Assertions_catchIllegalArgumentException_Test.java b/src/test/java/org/assertj/core/api/Assertions_catchIllegalArgumentException_Test.java
new file mode 100644
--- /dev/null
+++ b/src/test/java/org/assertj/core/api/Assertions_catchIllegalArgumentException_Test.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2021 the original author or authors.
+ */
+package org.assertj.core.api;
+
+import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.catchIllegalArgumentException;
+import static org.assertj.core.api.Assertions_catchThrowable_Test.codeThrowing;
+import static org.assertj.core.api.BDDAssertions.then;
+import static org.assertj.core.util.AssertionsUtil.expectAssertionError;
+import static org.mockito.Mockito.mock;
+
+class Assertions_catchIllegalArgumentException_Test {
+
+  @Test
+  void catchIllegalArgumentException_should_fail_with_good_message_if_wrong_type() {
+    // GIVEN
+    ThrowingCallable code = () -> catchIllegalArgumentException(raisingException("boom!!"));
+    // WHEN
+    AssertionError assertionError = expectAssertionError(code);
+    // THEN
+    assertThat(assertionError).hasMessageContainingAll(Exception.class.getName(), IllegalArgumentException.class.getName());
+  }
+
+  @Test
+  void catchIllegalArgumentException_should_succeed_and_return_actual_instance_with_correct_class() {
+    // GIVEN
+    final IllegalArgumentException expected = new IllegalArgumentException("boom!!");
+    // WHEN
+    IllegalArgumentException actual = catchIllegalArgumentException(codeThrowing(expected));
+    // THEN
+    then(actual).isSameAs(expected);
+  }
+
+  @Test
+  void catchIllegalArgumentException_should_succeed_and_return_null_if_no_exception_thrown() {
+    // WHEN
+    IllegalArgumentException actual = catchIllegalArgumentException(() -> {});
+    // THEN
+    then(actual).isNull();
+  }
+
+  @Test
+  void catchIllegalArgumentException_should_catch_mocked_throwable() {
+    // GIVEN
+    IllegalArgumentException exception = mock(IllegalArgumentException.class);
+    // WHEN
+    Throwable actual = catchIllegalArgumentException(codeThrowing(exception));
+    // THEN
+    then(actual).isSameAs(exception);
+  }
+
+  static ThrowingCallable raisingException(final String reason) {
+    return codeThrowing(new Exception(reason));
+  }
+
+}
diff --git a/src/test/java/org/assertj/core/api/Assertions_catchIllegalStateException_Test.java b/src/test/java/org/assertj/core/api/Assertions_catchIllegalStateException_Test.java
new file mode 100644
--- /dev/null
+++ b/src/test/java/org/assertj/core/api/Assertions_catchIllegalStateException_Test.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2021 the original author or authors.
+ */
+package org.assertj.core.api;
+
+import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.catchIllegalStateException;
+import static org.assertj.core.api.Assertions_catchThrowable_Test.codeThrowing;
+import static org.assertj.core.api.BDDAssertions.then;
+import static org.assertj.core.util.AssertionsUtil.expectAssertionError;
+import static org.mockito.Mockito.mock;
+
+class Assertions_catchIllegalStateException_Test {
+
+  @Test
+  void catchIllegalStateException_should_fail_with_good_message_if_wrong_type() {
+    // GIVEN
+    ThrowingCallable code = () -> catchIllegalStateException(raisingException("boom!!"));
+    // WHEN
+    AssertionError assertionError = expectAssertionError(code);
+    // THEN
+    assertThat(assertionError).hasMessageContainingAll(IllegalStateException.class.getName(), Exception.class.getName());
+  }
+
+  @Test
+  void catchIllegalStateException_should_succeed_and_return_actual_instance_with_correct_class() {
+    // GIVEN
+    final IllegalStateException expected = new IllegalStateException("boom!!");
+    // WHEN
+    IllegalStateException actual = catchIllegalStateException(codeThrowing(expected));
+    // THEN
+    then(actual).isSameAs(expected);
+  }
+
+  @Test
+  void catchIllegalStateException_should_succeed_and_return_null_if_no_exception_thrown() {
+    // WHEN
+    IllegalStateException actual = catchIllegalStateException(() -> {});
+    // THEN
+    then(actual).isNull();
+  }
+
+  @Test
+  void catchIllegalStateException_should_catch_mocked_throwable() {
+    // GIVEN
+    IllegalStateException illegalStateException = mock(IllegalStateException.class);
+    // WHEN
+    Throwable actual = catchIllegalStateException(codeThrowing(illegalStateException));
+    // THEN
+    then(actual).isSameAs(illegalStateException);
+  }
+
+  static ThrowingCallable raisingException(final String reason) {
+    return codeThrowing(new Exception(reason));
+  }
+
+}
diff --git a/src/test/java/org/assertj/core/api/Assertions_catchIndexOutOfBoundsException_Test.java b/src/test/java/org/assertj/core/api/Assertions_catchIndexOutOfBoundsException_Test.java
new file mode 100644
--- /dev/null
+++ b/src/test/java/org/assertj/core/api/Assertions_catchIndexOutOfBoundsException_Test.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2021 the original author or authors.
+ */
+package org.assertj.core.api;
+
+import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.catchIndexOutOfBoundsException;
+import static org.assertj.core.api.Assertions_catchThrowable_Test.codeThrowing;
+import static org.assertj.core.api.BDDAssertions.then;
+import static org.assertj.core.util.AssertionsUtil.expectAssertionError;
+import static org.mockito.Mockito.mock;
+
+class Assertions_catchIndexOutOfBoundsException_Test {
+
+  @Test
+  void catchIndexOutOfBoundsException_should_fail_with_good_message_if_wrong_type() {
+    // GIVEN
+    ThrowingCallable code = () -> catchIndexOutOfBoundsException(raisingException("boom!!"));
+    // WHEN
+    AssertionError assertionError = expectAssertionError(code);
+    // THEN
+    assertThat(assertionError).hasMessageContainingAll(IndexOutOfBoundsException.class.getName(), Exception.class.getName());
+  }
+
+  @Test
+  void catchIndexOutOfBoundsException_should_succeed_and_return_actual_instance_with_correct_class() {
+    // GIVEN
+    final IndexOutOfBoundsException expected = new IndexOutOfBoundsException("boom!!");
+    // WHEN
+    IndexOutOfBoundsException actual = catchIndexOutOfBoundsException(codeThrowing(expected));
+    // THEN
+    then(actual).isSameAs(expected);
+  }
+
+  @Test
+  void catchIndexOutOfBoundsException_should_succeed_and_return_null_if_no_exception_thrown() {
+    // WHEN
+    IndexOutOfBoundsException actual = catchIndexOutOfBoundsException(() -> {});
+    // THEN
+    then(actual).isNull();
+  }
+
+  @Test
+  void catchIndexOutOfBoundsException_should_catch_mocked_throwable() {
+    // GIVEN
+    IndexOutOfBoundsException indexOutOfBoundsException = mock(IndexOutOfBoundsException.class);
+    // WHEN
+    Throwable actual = catchIndexOutOfBoundsException(codeThrowing(indexOutOfBoundsException));
+    // THEN
+    then(actual).isSameAs(indexOutOfBoundsException);
+  }
+
+  static ThrowingCallable raisingException(final String reason) {
+    return codeThrowing(new Exception(reason));
+  }
+
+}
diff --git a/src/test/java/org/assertj/core/api/Assertions_catchNullPointerException_Test.java b/src/test/java/org/assertj/core/api/Assertions_catchNullPointerException_Test.java
new file mode 100644
--- /dev/null
+++ b/src/test/java/org/assertj/core/api/Assertions_catchNullPointerException_Test.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2021 the original author or authors.
+ */
+package org.assertj.core.api;
+
+import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.catchNullPointerException;
+import static org.assertj.core.api.Assertions_catchThrowable_Test.codeThrowing;
+import static org.assertj.core.api.BDDAssertions.then;
+import static org.assertj.core.util.AssertionsUtil.expectAssertionError;
+import static org.mockito.Mockito.mock;
+
+class Assertions_catchNullPointerException_Test {
+
+  @Test
+  void catchNullPointerException_should_fail_with_good_message_if_wrong_type() {
+    // GIVEN
+    ThrowingCallable code = () -> catchNullPointerException(raisingException("boom!!"));
+    // WHEN
+    AssertionError assertionError = expectAssertionError(code);
+    // THEN
+    assertThat(assertionError).hasMessageContainingAll(Exception.class.getName(), NullPointerException.class.getName());
+  }
+
+  @Test
+  void catchNullPointerException_should_succeed_and_return_actual_instance_with_correct_class() {
+    // GIVEN
+    final NullPointerException expected = new NullPointerException("boom!!");
+    // WHEN
+    NullPointerException actual = catchNullPointerException(codeThrowing(expected));
+    // THEN
+    then(actual).isSameAs(expected);
+  }
+
+  @Test
+  void catchNullPointerException_should_succeed_and_return_null_if_no_exception_thrown() {
+    // WHEN
+    NullPointerException actual = catchNullPointerException(() -> {});
+    // THEN
+    then(actual).isNull();
+  }
+
+  @Test
+  void catchNullPointerException_should_catch_mocked_throwable() {
+    // GIVEN
+    NullPointerException exception = mock(NullPointerException.class);
+    // WHEN
+    Throwable actual = catchNullPointerException(codeThrowing(exception));
+    // THEN
+    then(actual).isSameAs(exception);
+  }
+
+  static ThrowingCallable raisingException(final String reason) {
+    return codeThrowing(new Exception(reason));
+  }
+
+}
diff --git a/src/test/java/org/assertj/core/api/Assertions_catchReflectiveOperationException_Test.java b/src/test/java/org/assertj/core/api/Assertions_catchReflectiveOperationException_Test.java
new file mode 100644
--- /dev/null
+++ b/src/test/java/org/assertj/core/api/Assertions_catchReflectiveOperationException_Test.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2021 the original author or authors.
+ */
+package org.assertj.core.api;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.catchReflectiveOperationException;
+import static org.assertj.core.api.Assertions_catchThrowable_Test.codeThrowing;
+import static org.assertj.core.api.BDDAssertions.then;
+import static org.assertj.core.util.AssertionsUtil.expectAssertionError;
+import static org.mockito.Mockito.mock;
+
+import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
+import org.junit.jupiter.api.Test;
+
+class Assertions_catchReflectiveOperationException_Test {
+
+  @Test
+  void catchReflectiveOperationException_should_fail_with_good_message_if_wrong_type() {
+    // GIVEN
+    ThrowingCallable code = () -> catchReflectiveOperationException(raisingException("boom!!"));
+    // WHEN
+    AssertionError assertionError = expectAssertionError(code);
+    // THEN
+    assertThat(assertionError).hasMessageContainingAll(ReflectiveOperationException.class.getName(), Exception.class.getName());
+  }
+
+  @Test
+  void catchReflectiveOperationException_should_succeed_and_return_actual_instance_with_correct_class() {
+    // GIVEN
+    final ReflectiveOperationException expected = new ReflectiveOperationException("boom!!");
+    // WHEN
+    ReflectiveOperationException actual = catchReflectiveOperationException(codeThrowing(expected));
+    // THEN
+    then(actual).isSameAs(expected);
+  }
+
+  @Test
+  void catchReflectiveOperationException_should_succeed_and_return_null_if_no_exception_thrown() {
+    // WHEN
+    ReflectiveOperationException actual = catchReflectiveOperationException(() -> {});
+    // THEN
+    then(actual).isNull();
+  }
+
+  @Test
+  void catchReflectiveOperationException_should_catch_mocked_throwable() {
+    // GIVEN
+    ReflectiveOperationException exception = mock(ReflectiveOperationException.class);
+    // WHEN
+    Throwable actual = catchReflectiveOperationException(codeThrowing(exception));
+    // THEN
+    then(actual).isSameAs(exception);
+  }
+
+  static ThrowingCallable raisingException(final String reason) {
+    return codeThrowing(new Exception(reason));
+  }
+
+}
diff --git a/src/test/java/org/assertj/core/api/Assertions_catchRuntimeException_Test.java b/src/test/java/org/assertj/core/api/Assertions_catchRuntimeException_Test.java
new file mode 100644
--- /dev/null
+++ b/src/test/java/org/assertj/core/api/Assertions_catchRuntimeException_Test.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2021 the original author or authors.
+ */
+package org.assertj.core.api;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.assertj.core.api.Assertions_catchThrowable_Test.codeThrowing;
+import static org.assertj.core.api.BDDAssertions.then;
+import static org.assertj.core.util.AssertionsUtil.expectAssertionError;
+import static org.mockito.Mockito.mock;
+import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
+import org.junit.jupiter.api.Test;
+
+class Assertions_catchRuntimeException_Test {
+
+  @Test
+  void catchRuntimeException_should_fail_with_good_message_if_wrong_type() {
+    // GIVEN
+    ThrowingCallable code = () -> catchRuntimeException(raisingException("boom!!"));
+    // WHEN
+    AssertionError assertionError = expectAssertionError(code);
+    // THEN
+    assertThat(assertionError).hasMessageContainingAll(RuntimeException.class.getName(), Exception.class.getName());
+  }
+
+  @Test
+  void catchRuntimeException_should_succeed_and_return_actual_instance_with_correct_class() {
+    // GIVEN
+    final RuntimeException expected = new RuntimeException("boom!!");
+    // WHEN
+    RuntimeException actual = catchRuntimeException(codeThrowing(expected));
+    // THEN
+    then(actual).isSameAs(expected);
+  }
+
+  @Test
+  void catchRuntimeException_should_succeed_and_return_null_if_no_exception_thrown() {
+    // WHEN
+    RuntimeException actual = catchRuntimeException(() -> {});
+    // THEN
+    then(actual).isNull();
+  }
+
+  @Test
+  void catchRuntimeException_should_catch_mocked_throwable() {
+    // GIVEN
+    RuntimeException runtimeException = mock(RuntimeException.class);
+    // WHEN
+    Throwable actual = catchRuntimeException(codeThrowing(runtimeException));
+    // THEN
+    then(actual).isSameAs(runtimeException);
+  }
+
+  static ThrowingCallable raisingException(final String reason) {
+    return codeThrowing(new Exception(reason));
+  }
+
+}
diff --git a/src/test/java/org/assertj/core/api/EntryPointAssertions_catchException_Test.java b/src/test/java/org/assertj/core/api/EntryPointAssertions_catchException_Test.java
new file mode 100644
--- /dev/null
+++ b/src/test/java/org/assertj/core/api/EntryPointAssertions_catchException_Test.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2021 the original author or authors.
+ */
+package org.assertj.core.api;
+
+import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import static org.assertj.core.api.BDDAssertions.then;
+
+class EntryPointAssertions_catchException_Test extends EntryPointAssertionsBaseTest {
+
+  private static final Exception EXCEPTION = new Exception();
+
+  @ParameterizedTest
+  @MethodSource("catchExceptions")
+  void should_catch_Exception(Function<ThrowingCallable, Exception> catchException) {
+    // GIVEN
+    ThrowingCallable throwingCallable = () -> {
+      throw EXCEPTION;
+    };
+    // WHEN
+    Exception throwable = catchException.apply(throwingCallable);
+    // THEN
+    then(throwable).isSameAs(EXCEPTION);
+  }
+
+  private static Stream<Function<ThrowingCallable, Exception>> catchExceptions() {
+    return Stream.of(Assertions::catchException, BDDAssertions::catchException, withAssertions::catchException);
+  }
+
+}
diff --git a/src/test/java/org/assertj/core/api/EntryPointAssertions_catchIOException_Test.java b/src/test/java/org/assertj/core/api/EntryPointAssertions_catchIOException_Test.java
new file mode 100644
--- /dev/null
+++ b/src/test/java/org/assertj/core/api/EntryPointAssertions_catchIOException_Test.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2021 the original author or authors.
+ */
+package org.assertj.core.api;
+
+import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.io.IOException;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import static org.assertj.core.api.BDDAssertions.then;
+
+class EntryPointAssertions_catchIOException_Test extends EntryPointAssertionsBaseTest {
+
+  private static final IOException IO_EXCEPTION = new IOException();
+
+  @ParameterizedTest
+  @MethodSource("catchIOExceptions")
+  void should_catch_IOException(Function<ThrowingCallable, IOException> catchIOException) {
+    // GIVEN
+    ThrowingCallable throwingCallable = () -> {
+      throw IO_EXCEPTION;
+    };
+    // WHEN
+    IOException throwable = catchIOException.apply(throwingCallable);
+    // THEN
+    then(throwable).isSameAs(IO_EXCEPTION);
+  }
+
+  private static Stream<Function<ThrowingCallable, IOException>> catchIOExceptions() {
+    return Stream.of(Assertions::catchIOException, BDDAssertions::catchIOException, withAssertions::catchIOException);
+  }
+
+}
diff --git a/src/test/java/org/assertj/core/api/EntryPointAssertions_catchIllegalArgumentException_Test.java b/src/test/java/org/assertj/core/api/EntryPointAssertions_catchIllegalArgumentException_Test.java
new file mode 100644
--- /dev/null
+++ b/src/test/java/org/assertj/core/api/EntryPointAssertions_catchIllegalArgumentException_Test.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2021 the original author or authors.
+ */
+package org.assertj.core.api;
+
+import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import static org.assertj.core.api.BDDAssertions.then;
+
+class EntryPointAssertions_catchIllegalArgumentException_Test extends EntryPointAssertionsBaseTest {
+
+  private static final IllegalArgumentException ILLEGAL_ARGUMENT_EXCEPTION = new IllegalArgumentException();
+
+  @ParameterizedTest
+  @MethodSource("catchIllegalArgumentExceptions")
+  void should_catch_IllegalArgumentException(Function<ThrowingCallable, IllegalArgumentException> catchIllegalArgumentExceptions) {
+    // GIVEN
+    ThrowingCallable throwingCallable = () -> {
+      throw ILLEGAL_ARGUMENT_EXCEPTION;
+    };
+    // WHEN
+    IllegalArgumentException throwable = catchIllegalArgumentExceptions.apply(throwingCallable);
+    // THEN
+    then(throwable).isSameAs(ILLEGAL_ARGUMENT_EXCEPTION);
+  }
+
+  private static Stream<Function<ThrowingCallable, IllegalArgumentException>> catchIllegalArgumentExceptions() {
+    return Stream.of(Assertions::catchIllegalArgumentException, BDDAssertions::catchIllegalArgumentException, withAssertions::catchIllegalArgumentException);
+  }
+
+}
diff --git a/src/test/java/org/assertj/core/api/EntryPointAssertions_catchIllegalStateException_Test.java b/src/test/java/org/assertj/core/api/EntryPointAssertions_catchIllegalStateException_Test.java
new file mode 100644
--- /dev/null
+++ b/src/test/java/org/assertj/core/api/EntryPointAssertions_catchIllegalStateException_Test.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2021 the original author or authors.
+ */
+package org.assertj.core.api;
+
+import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import static org.assertj.core.api.BDDAssertions.then;
+
+class EntryPointAssertions_catchIllegalStateException_Test extends EntryPointAssertionsBaseTest {
+
+  private static final IllegalStateException ILLEGAL_STATE_EXCEPTION = new IllegalStateException();
+
+  @ParameterizedTest
+  @MethodSource("catchIllegalStateExceptions")
+  void should_catch_IllegalStateException(Function<ThrowingCallable, IllegalStateException> catchIllegalStateException) {
+    // GIVEN
+    ThrowingCallable throwingCallable = () -> {
+      throw ILLEGAL_STATE_EXCEPTION;
+    };
+    // WHEN
+    IllegalStateException throwable = catchIllegalStateException.apply(throwingCallable);
+    // THEN
+    then(throwable).isSameAs(ILLEGAL_STATE_EXCEPTION);
+  }
+
+  private static Stream<Function<ThrowingCallable, IllegalStateException>> catchIllegalStateExceptions() {
+    return Stream.of(Assertions::catchIllegalStateException, BDDAssertions::catchIllegalStateException, withAssertions::catchIllegalStateException);
+  }
+
+}
diff --git a/src/test/java/org/assertj/core/api/EntryPointAssertions_catchIndexOutOfBoundsException_Test.java b/src/test/java/org/assertj/core/api/EntryPointAssertions_catchIndexOutOfBoundsException_Test.java
new file mode 100644
--- /dev/null
+++ b/src/test/java/org/assertj/core/api/EntryPointAssertions_catchIndexOutOfBoundsException_Test.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2021 the original author or authors.
+ */
+package org.assertj.core.api;
+
+import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import static org.assertj.core.api.BDDAssertions.then;
+
+class EntryPointAssertions_catchIndexOutOfBoundsException_Test extends EntryPointAssertionsBaseTest {
+
+  private static final IndexOutOfBoundsException INDEX_OUT_OF_BOUNDS_EXCEPTION = new IndexOutOfBoundsException();
+
+  @ParameterizedTest
+  @MethodSource("catchIndexOutOfBoundsExceptions")
+  void should_catch_IndexOutOfBoundsException(Function<ThrowingCallable, IndexOutOfBoundsException> catchIndexOutOfBoundsException) {
+    // GIVEN
+    ThrowingCallable throwingCallable = () -> {
+      throw INDEX_OUT_OF_BOUNDS_EXCEPTION;
+    };
+    // WHEN
+    IndexOutOfBoundsException throwable = catchIndexOutOfBoundsException.apply(throwingCallable);
+    // THEN
+    then(throwable).isSameAs(INDEX_OUT_OF_BOUNDS_EXCEPTION);
+  }
+
+  private static Stream<Function<ThrowingCallable, IndexOutOfBoundsException>> catchIndexOutOfBoundsExceptions() {
+    return Stream.of(Assertions::catchIndexOutOfBoundsException, BDDAssertions::catchIndexOutOfBoundsException, withAssertions::catchIndexOutOfBoundsException);
+  }
+
+}
diff --git a/src/test/java/org/assertj/core/api/EntryPointAssertions_catchNullPointerException_Test.java b/src/test/java/org/assertj/core/api/EntryPointAssertions_catchNullPointerException_Test.java
new file mode 100644
--- /dev/null
+++ b/src/test/java/org/assertj/core/api/EntryPointAssertions_catchNullPointerException_Test.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2021 the original author or authors.
+ */
+package org.assertj.core.api;
+
+import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import static org.assertj.core.api.BDDAssertions.then;
+
+class EntryPointAssertions_catchNullPointerException_Test extends EntryPointAssertionsBaseTest {
+
+  private static final NullPointerException NULL_POINTER_EXCEPTION = new NullPointerException();
+
+  @ParameterizedTest
+  @MethodSource("catchNullPointerExceptions")
+  void should_catch_NullPointerException(Function<ThrowingCallable, NullPointerException> catchNullPointerException) {
+    // GIVEN
+    ThrowingCallable throwingCallable = () -> {
+      throw NULL_POINTER_EXCEPTION;
+    };
+    // WHEN
+    NullPointerException throwable = catchNullPointerException.apply(throwingCallable);
+    // THEN
+    then(throwable).isSameAs(NULL_POINTER_EXCEPTION);
+  }
+
+  private static Stream<Function<ThrowingCallable, NullPointerException>> catchNullPointerExceptions() {
+    return Stream.of(Assertions::catchNullPointerException, BDDAssertions::catchNullPointerException, withAssertions::catchNullPointerException);
+  }
+
+}
diff --git a/src/test/java/org/assertj/core/api/EntryPointAssertions_catchReflectiveOperationException_Test.java b/src/test/java/org/assertj/core/api/EntryPointAssertions_catchReflectiveOperationException_Test.java
new file mode 100644
--- /dev/null
+++ b/src/test/java/org/assertj/core/api/EntryPointAssertions_catchReflectiveOperationException_Test.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2021 the original author or authors.
+ */
+package org.assertj.core.api;
+
+import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import static org.assertj.core.api.BDDAssertions.then;
+
+class EntryPointAssertions_catchReflectiveOperationException_Test extends EntryPointAssertionsBaseTest {
+
+  private static final ReflectiveOperationException REFLECTIVE_OPERATION_EXCEPTION = new ReflectiveOperationException();
+
+  @ParameterizedTest
+  @MethodSource("catchReflectiveOperationExceptions")
+  void should_catch_ReflectiveOperationException(Function<ThrowingCallable, ReflectiveOperationException> catchReflectiveOperationExceptions) {
+    // GIVEN
+    ThrowingCallable throwingCallable = () -> {
+      throw REFLECTIVE_OPERATION_EXCEPTION;
+    };
+    // WHEN
+    ReflectiveOperationException throwable = catchReflectiveOperationExceptions.apply(throwingCallable);
+    // THEN
+    then(throwable).isSameAs(REFLECTIVE_OPERATION_EXCEPTION);
+  }
+
+  private static Stream<Function<ThrowingCallable, ReflectiveOperationException>> catchReflectiveOperationExceptions() {
+    return Stream.of(Assertions::catchReflectiveOperationException, BDDAssertions::catchReflectiveOperationException, withAssertions::catchReflectiveOperationException);
+  }
+
+}
diff --git a/src/test/java/org/assertj/core/api/EntryPointAssertions_catchRuntimeException_Test.java b/src/test/java/org/assertj/core/api/EntryPointAssertions_catchRuntimeException_Test.java
new file mode 100644
--- /dev/null
+++ b/src/test/java/org/assertj/core/api/EntryPointAssertions_catchRuntimeException_Test.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Copyright 2012-2021 the original author or authors.
+ */
+package org.assertj.core.api;
+
+import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import static org.assertj.core.api.BDDAssertions.then;
+
+class EntryPointAssertions_catchRuntimeException_Test extends EntryPointAssertionsBaseTest {
+
+  private static final RuntimeException RUNTIME_EXCEPTION = new RuntimeException();
+
+  @ParameterizedTest
+  @MethodSource("catchRuntimeExceptions")
+  void should_catch_RuntimeException(Function<ThrowingCallable, RuntimeException> catchRuntimeException) {
+    // GIVEN
+    ThrowingCallable throwingCallable = () -> {
+      throw RUNTIME_EXCEPTION;
+    };
+    // WHEN
+    RuntimeException throwable = catchRuntimeException.apply(throwingCallable);
+    // THEN
+    then(throwable).isSameAs(RUNTIME_EXCEPTION);
+  }
+
+  private static Stream<Function<ThrowingCallable, RuntimeException>> catchRuntimeExceptions() {
+    return Stream.of(Assertions::catchRuntimeException, BDDAssertions::catchRuntimeException, withAssertions::catchRuntimeException);
+  }
+
+}