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.
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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.