Skip to content

Commit

Permalink
Add fail(Throwable) and fail() variants
Browse files Browse the repository at this point in the history
Fix #3204
  • Loading branch information
izeye authored and joel-costigliola committed Apr 10, 2024
1 parent 8034f00 commit a962107
Show file tree
Hide file tree
Showing 10 changed files with 709 additions and 445 deletions.
Expand Up @@ -53,7 +53,7 @@ public void assertAll() {
*
* @param <T> dummy return value type
* @param failureMessage error message.
* @return nothing, it's just to be used in {@code doSomething(optional.orElseGet(() -> fail("boom")));}.
* @return nothing, it's just to be used in {@code doSomething(optional.orElseGet(() -> softly.fail("boom")));}.
* @since 2.6.0 / 3.6.0
*/
@CanIgnoreReturnValue
Expand All @@ -63,13 +63,27 @@ public <T> T fail(String failureMessage) {
return null;
}

/**
* Fails with an empty message to be used in code like:
* <pre><code class='java'> doSomething(optional.orElseGet(() -> softly.fail()));</code></pre>
*
* @param <T> dummy return value type
* @return nothing, it's just to be used in {@code doSomething(optional.orElseGet(() -> softly.fail()));}.
* @since 3.26.0
*/
@CanIgnoreReturnValue
public <T> T fail() {
// pass an empty string because passing null results in a "null" error message.
return fail("");
}

/**
* Fails with the given message built like {@link String#format(String, Object...)}.
*
* @param <T> dummy return value type
* @param failureMessage error message.
* @param args Arguments referenced by the format specifiers in the format string.
* @return nothing, it's just to be used in {@code doSomething(optional.orElseGet(() -> fail("boom")));}.
* @return nothing, it's just to be used in {@code doSomething(optional.orElseGet(() -> softly.fail("boom")));}.
* @since 2.6.0 / 3.6.0
*/
@CanIgnoreReturnValue
Expand All @@ -83,7 +97,7 @@ public <T> T fail(String failureMessage, Object... args) {
* @param <T> dummy return value type
* @param failureMessage error message.
* @param realCause cause of the error.
* @return nothing, it's just to be used in {@code doSomething(optional.orElseGet(() -> fail("boom")));}.
* @return nothing, it's just to be used in {@code doSomething(optional.orElseGet(() -> softly.fail("boom")));}.
* @since 2.6.0 / 3.6.0
*/
@CanIgnoreReturnValue
Expand All @@ -94,6 +108,22 @@ public <T> T fail(String failureMessage, Throwable realCause) {
return null;
}

/**
* Fails with the {@link Throwable} that caused the failure and an empty message.
* <p>
* Example:
* <pre><code class='java'> doSomething(optional.orElseGet(() -> softly.fail(cause)));</code></pre>
*
* @param <T> dummy return value type
* @param realCause cause of the error.
* @return nothing, it's just to be used in {@code doSomething(optional.orElseGet(() -> softly.fail(cause)));}.
* @since 3.26.0
*/
@CanIgnoreReturnValue
public <T> T fail(Throwable realCause) {
return fail("", realCause);
}

/**
* Fails with a message explaining that a {@link Throwable} of given class was expected to be thrown
* but had not been.
Expand Down
31 changes: 31 additions & 0 deletions assertj-core/src/main/java/org/assertj/core/api/Assertions.java
Expand Up @@ -1799,6 +1799,20 @@ public static <T> T fail(String failureMessage) {
return Fail.fail(failureMessage);
}

/**
* Throws an {@link AssertionError} with an empty message to be used in code like:
* <pre><code class='java'> doSomething(optional.orElseGet(() -> fail()));</code></pre>
*
* @param <T> dummy return value type
* @return nothing, it's just to be used in {@code doSomething(optional.orElseGet(() -> fail()));}.
* @throws AssertionError with an empty message.
* @since 3.26.0
*/
@CanIgnoreReturnValue
public static <T> T fail() {
return Fail.fail();
}

/**
* Throws an {@link AssertionError} with the given message built as {@link String#format(String, Object...)}.
*
Expand Down Expand Up @@ -1826,6 +1840,23 @@ public static <T> T fail(String failureMessage, Throwable realCause) {
return Fail.fail(failureMessage, realCause);
}

/**
* Throws an {@link AssertionError} with the {@link Throwable} that caused the failure and an empty message.
* <p>
* Example:
* <pre><code class='java'> doSomething(optional.orElseGet(() -> fail(cause)));</code></pre>
*
* @param <T> dummy return value type
* @param realCause cause of the error.
* @return nothing, it's just to be used in {@code doSomething(optional.orElseGet(() -> fail(cause)));}.
* @throws AssertionError with the {@link Throwable} that caused the failure.
*/
@CanIgnoreReturnValue
public static <T> T fail(Throwable realCause) {
// pass an empty string because passing null results in a "null" error message.
return fail("", realCause);
}

/**
* Throws an {@link AssertionError} with a message explaining that a {@link Throwable} of given class was expected to be thrown
* but had not been.
Expand Down
Expand Up @@ -971,6 +971,16 @@ public static void fail(String failureMessage) {
Fail.fail(failureMessage);
}

/**
* Only delegate to {@link Fail#fail()} so that {@link Assertions} offers a full feature entry point to all Assertj
* features (but you can use {@code Fail} if you prefer).
*
* @throws AssertionError without message.
*/
public static void fail() {
Fail.fail();
}

/**
* Only delegate to {@link Fail#fail(String, Throwable)} so that Assertions offers a full feature entry point to all
* AssertJ features (but you can use Fail if you prefer).
Expand All @@ -983,6 +993,17 @@ public static void fail(String failureMessage, Throwable realCause) {
Fail.fail(failureMessage, realCause);
}

/**
* Only delegate to {@link Fail#fail(Throwable)} so that Assertions offers a full feature entry point to all
* AssertJ features (but you can use Fail if you prefer).
*
* @param realCause cause of the error.
* @throws AssertionError with the {@link Throwable} that caused the failure.
*/
public static void fail(Throwable realCause) {
Fail.fail(realCause);
}

/**
* Only delegate to {@link Fail#failBecauseExceptionWasNotThrown(Class)} so that Assertions offers a full feature
* entry point to all AssertJ features (but you can use Fail if you prefer).
Expand Down
26 changes: 26 additions & 0 deletions assertj-core/src/main/java/org/assertj/core/api/BDDAssertions.java
Expand Up @@ -2296,6 +2296,20 @@ public static <T> T fail(String failureMessage) {
return Assertions.fail(failureMessage);
}

/**
* Throws an {@link AssertionError} with an empty message to be used in code like:
* <pre><code class='java'> doSomething(optional.orElseGet(() -> fail()));</code></pre>
*
* @param <T> dummy return value type
* @return nothing, it's just to be used in {@code doSomething(optional.orElseGet(() -> fail()));}.
* @throws AssertionError with an empty message.
* @since 3.26.0
*/
@CanIgnoreReturnValue
public static <T> T fail() {
return Assertions.fail();
}

/**
* Throws an {@link AssertionError} with the given message built as {@link String#format(String, Object...)}.
*
Expand Down Expand Up @@ -2327,6 +2341,18 @@ public static <T> T fail(String failureMessage, Throwable realCause) {
return Assertions.fail(failureMessage, realCause);
}

/**
* Throws an {@link AssertionError} with the {@link Throwable} that caused the failure.
* @param <T> dummy return value type
* @param realCause cause of the error.
* @return nothing, it's just to be used in {@code doSomething(optional.orElseGet(() -> fail(cause)));}.
* @throws AssertionError with the {@link Throwable} that caused the failure.
*/
@CanIgnoreReturnValue
public static <T> T fail(Throwable realCause) {
return fail(null, realCause);
}

/**
* Throws an {@link AssertionError} with a message explaining that a {@link Throwable} of given class was expected to be thrown
* but had not been.
Expand Down
28 changes: 28 additions & 0 deletions assertj-core/src/main/java/org/assertj/core/api/Fail.java
Expand Up @@ -46,6 +46,21 @@ public static <T> T fail(String failureMessage) {
throw Failures.instance().failure(failureMessage);
}

/**
* Throws an {@link AssertionError} with an empty message to be used in code like:
* <pre><code class='java'> doSomething(optional.orElseGet(() -> fail()));</code></pre>
*
* @param <T> dummy return value type
* @return nothing, it's just to be used in {@code doSomething(optional.orElseGet(() -> fail()));}.
* @throws AssertionError with an empty message.
* @since 3.26.0
*/
@CanIgnoreReturnValue
public static <T> T fail() {
// pass an empty string because passing null results in a "null" error message.
return fail("");
}

/**
* Throws an {@link AssertionError} with the given message built as {@link String#format(String, Object...)}.
*
Expand Down Expand Up @@ -76,6 +91,19 @@ public static <T> T fail(String failureMessage, Throwable realCause) {
throw error;
}

/**
* Throws an {@link AssertionError} with the {@link Throwable} that caused the failure.
*
* @param <T> dummy return value type
* @param realCause cause of the error.
* @return nothing, it's just to be used in {@code doSomething(optional.orElseGet(() -> fail(cause)));}.
* @throws AssertionError with the {@link Throwable} that caused the failure.
*/
@CanIgnoreReturnValue
public static <T> T fail(Throwable realCause) {
return fail(null, realCause);
}

/**
* Throws an {@link AssertionError} with a message explaining that a {@link Throwable} of given class was expected to be thrown
* but had not been.
Expand Down
Expand Up @@ -173,6 +173,20 @@ default <T> T fail(final String failureMessage) {
return Assertions.fail(failureMessage);
}

/**
* Throws an {@link AssertionError} with an empty message to be used in code like:
* <pre><code class='java'> doSomething(optional.orElseGet(() -> fail()));</code></pre>
*
* @param <T> dummy return value type
* @return nothing, it's just to be used in {@code doSomething(optional.orElseGet(() -> fail()));}.
* @throws AssertionError with an empty message.
* @since 3.26.0
*/
@CanIgnoreReturnValue
default <T> T fail() {
return Assertions.fail();
}

/**
* Throws an {@link AssertionError} with the given message built as {@link String#format(String, Object...)}.
*
Expand Down Expand Up @@ -202,6 +216,19 @@ default <T> T fail(final String failureMessage, final Throwable realCause) {
return Assertions.fail(failureMessage, realCause);
}

/**
* Throws an {@link AssertionError} with the {@link Throwable} that caused the failure.
*
* @param <T> dummy return value type
* @param realCause cause of the error.
* @return nothing, it's just to be used in {@code doSomething(optional.orElseGet(() -> fail(cause)));}.
* @throws AssertionError with the {@link Throwable} that caused the failure.
*/
@CanIgnoreReturnValue
default <T> T fail(final Throwable realCause) {
return fail(null, realCause);
}

/**
* Creates a new <code>{@link Not}</code>.
*
Expand Down
Expand Up @@ -827,15 +827,24 @@ public void onAssertionErrorCollected(AssertionError assertionError) {
}
}

@Test
void should_return_failure_after_fail_without_message() {
// WHEN
softly.fail();
// THEN
then(softly.errorsCollected()).singleElement(as(THROWABLE))
.message().isEmpty();
}

@Test
void should_return_failure_after_fail() {
// GIVEN
String failureMessage = "Should not reach here";
// WHEN
softly.fail(failureMessage);
// THEN
assertThat(softly.errorsCollected()).hasSize(1);
assertThat(softly.errorsCollected().get(0)).hasMessageStartingWith(failureMessage);
then(softly.errorsCollected()).singleElement(as(THROWABLE))
.hasMessageStartingWith(failureMessage);
}

@Test
Expand All @@ -845,22 +854,33 @@ void should_return_failure_after_fail_with_parameters() {
// WHEN
softly.fail(failureMessage, "here", "here");
// THEN
assertThat(softly.errorsCollected()).hasSize(1);
assertThat(softly.errorsCollected().get(0)).hasMessageStartingWith("Should not reach here or here");
then(softly.errorsCollected()).singleElement(as(THROWABLE))
.hasMessageStartingWith("Should not reach here or here");
}

@Test
void should_return_failure_after_fail_with_cause() {
// GIVEN
IllegalStateException realCause = new IllegalStateException();
// WHEN
softly.fail(realCause);
// THEN
then(softly.errorsCollected()).singleElement(as(THROWABLE))
.hasMessage("")
.cause().isEqualTo(realCause);
}

@Test
void should_return_failure_after_fail_with_throwable() {
void should_return_failure_after_fail_with_message_and_cause() {
// GIVEN
String failureMessage = "Should not reach here";
IllegalStateException realCause = new IllegalStateException();
// WHEN
softly.fail(failureMessage, realCause);
// THEN
List<Throwable> errorsCollected = softly.errorsCollected();
assertThat(errorsCollected).hasSize(1);
assertThat(errorsCollected.get(0)).hasMessageStartingWith(failureMessage);
assertThat(errorsCollected.get(0).getCause()).isEqualTo(realCause);
then(softly.errorsCollected()).singleElement(as(THROWABLE))
.hasMessageStartingWith(failureMessage)
.cause().isEqualTo(realCause);
}

@Test
Expand Down
Expand Up @@ -19,6 +19,7 @@
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;

import org.junit.jupiter.api.DisplayName;
Expand Down Expand Up @@ -90,4 +91,34 @@ void should_return_a_value_to_allow_using_optional_orElseGet(Function<String, In
private void doSomethingWithInt(@SuppressWarnings("unused") int parameter) {
// just to illustrate the previous test
}

@ParameterizedTest
@MethodSource
void should_fail_without_message(Supplier<Void> supplier) {
// WHEN
AssertionError assertionError = expectAssertionError(() -> supplier.get());
// THEN
then(assertionError).hasMessage("");
}

private static Stream<Supplier<Void>> should_fail_without_message() {
return Stream.of(Assertions::fail, BDDAssertions::fail, withAssertions::fail);
}

@ParameterizedTest
@MethodSource
<T> void should_fail_without_message_but_with_root_cause(Function<Throwable, T> failWithCauseFunction) {
// GIVEN
String message = "boom!";
Exception cause = new Exception(message);
// WHEN
AssertionError assertionError = expectAssertionError(() -> failWithCauseFunction.apply(cause));
// THEN
then(assertionError).hasCause(cause);
}

private static <T> Stream<Function<Throwable, T>> should_fail_without_message_but_with_root_cause() {
return Stream.of(Assertions::fail, BDDAssertions::fail, withAssertions::fail);
}

}

0 comments on commit a962107

Please sign in to comment.