Skip to content

Commit cf06398

Browse files
findepijoel-costigliola
authored andcommitted
Provide value when assertThatThrownBy/thenThrownBy fail
Fix #3043
1 parent 12195d8 commit cf06398

File tree

5 files changed

+108
-2
lines changed

5 files changed

+108
-2
lines changed

assertj-core/src/main/java/org/assertj/core/api/Assertions.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
*/
1313
package org.assertj.core.api;
1414

15+
import static java.lang.String.format;
1516
import static org.assertj.core.configuration.ConfigurationProvider.CONFIGURATION_PROVIDER;
1617
import static org.assertj.core.data.Percentage.withPercentage;
1718

@@ -75,6 +76,7 @@
7576
import java.util.stream.Stream;
7677

7778
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
79+
import org.assertj.core.api.ThrowableAssert.ThrowingCallableWithValue;
7880
import org.assertj.core.api.filter.FilterOperator;
7981
import org.assertj.core.api.filter.Filters;
8082
import org.assertj.core.api.filter.InFilter;
@@ -96,6 +98,7 @@
9698
import org.assertj.core.description.Description;
9799
import org.assertj.core.groups.Properties;
98100
import org.assertj.core.groups.Tuple;
101+
import org.assertj.core.internal.Failures;
99102
import org.assertj.core.presentation.BinaryRepresentation;
100103
import org.assertj.core.presentation.HexadecimalRepresentation;
101104
import org.assertj.core.presentation.Representation;
@@ -1210,6 +1213,26 @@ public static <T extends Throwable> AbstractThrowableAssert<?, T> assertThat(T a
12101213
return assertThat(catchThrowable(shouldRaiseThrowable)).hasBeenThrown();
12111214
}
12121215

1216+
/**
1217+
* Similar to {@link #assertThatThrownBy(ThrowingCallable)}, but when the called code returns a value instead of
1218+
* throwing, the assertion error shows the returned value to help understand what went wrong.
1219+
*
1220+
* @param shouldRaiseThrowable The {@link ThrowingCallableWithValue} or lambda with the code that should raise the throwable.
1221+
* @return the created {@link ThrowableAssert}.
1222+
* @since 3.25.0
1223+
*/
1224+
@CanIgnoreReturnValue
1225+
public static AbstractThrowableAssert<?, ? extends Throwable> assertThatThrownBy(
1226+
ThrowingCallableWithValue shouldRaiseThrowable) {
1227+
Object value;
1228+
try {
1229+
value = shouldRaiseThrowable.call();
1230+
} catch (Throwable throwable) {
1231+
return assertThat(throwable);
1232+
}
1233+
throw Failures.instance().failure(format("Expecting code to raise a throwable, but it returned [%s] instead", value));
1234+
}
1235+
12131236
/**
12141237
* Allows to capture and then assert on a {@link Throwable} like {@code assertThatThrownBy(ThrowingCallable)} but this method
12151238
* let you set the assertion description the same way you do with {@link AbstractAssert#as(String, Object...) as(String, Object...)}.
@@ -1248,6 +1271,26 @@ public static <T extends Throwable> AbstractThrowableAssert<?, T> assertThat(T a
12481271
return assertThat(catchThrowable(shouldRaiseThrowable)).as(description, args).hasBeenThrown();
12491272
}
12501273

1274+
/**
1275+
* Similar to {@link #assertThatThrownBy(ThrowingCallable, String, Object...)}, but when the called code returns a value
1276+
* instead of throwing, the assertion error shows the returned value to help understand what went wrong.
1277+
*
1278+
* @param shouldRaiseThrowable The {@link ThrowingCallableWithValue} or lambda with the code that should raise the throwable.
1279+
* @return the created {@link ThrowableAssert}.
1280+
* @since 3.25.0
1281+
*/
1282+
@CanIgnoreReturnValue
1283+
public static AbstractThrowableAssert<?, ? extends Throwable> assertThatThrownBy(ThrowingCallableWithValue shouldRaiseThrowable,
1284+
String description, Object... args) {
1285+
Object value;
1286+
try {
1287+
value = shouldRaiseThrowable.call();
1288+
} catch (Throwable throwable) {
1289+
return assertThat(throwable).as(description, args);
1290+
}
1291+
throw Failures.instance().failure(format("Expecting code to raise a throwable, but it returned [%s] instead", value));
1292+
}
1293+
12511294
/**
12521295
* Allows to capture and then assert on a {@link Throwable} (easier done with lambdas).
12531296
* <p>

assertj-core/src/main/java/org/assertj/core/api/BDDAssertions.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
*/
1313
package org.assertj.core.api;
1414

15+
import static java.lang.String.format;
16+
1517
import java.io.File;
1618
import java.io.IOException;
1719
import java.io.InputStream;
@@ -72,6 +74,7 @@
7274
import java.util.stream.Stream;
7375

7476
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
77+
import org.assertj.core.api.ThrowableAssert.ThrowingCallableWithValue;
7578
import org.assertj.core.api.filter.FilterOperator;
7679
import org.assertj.core.api.filter.InFilter;
7780
import org.assertj.core.api.filter.NotFilter;
@@ -89,6 +92,7 @@
8992
import org.assertj.core.description.Description;
9093
import org.assertj.core.groups.Properties;
9194
import org.assertj.core.groups.Tuple;
95+
import org.assertj.core.internal.Failures;
9296
import org.assertj.core.presentation.BinaryRepresentation;
9397
import org.assertj.core.presentation.HexadecimalRepresentation;
9498
import org.assertj.core.presentation.Representation;
@@ -1316,6 +1320,25 @@ public static <T extends Throwable> AbstractThrowableAssert<?, T> then(T actual)
13161320
return assertThat(catchThrowable(shouldRaiseThrowable)).hasBeenThrown();
13171321
}
13181322

1323+
/**
1324+
* Similar to {@link #thenThrownBy(ThrowingCallable)}, but when the called code returns a value instead of
1325+
* throwing, the assertion error shows the returned value to help understand what went wrong.
1326+
*
1327+
* @param shouldRaiseThrowable The {@link ThrowingCallableWithValue} or lambda with the code that should raise the throwable.
1328+
* @return the created {@link ThrowableAssert}.
1329+
* @since 3.25.0
1330+
*/
1331+
@CanIgnoreReturnValue
1332+
public static AbstractThrowableAssert<?, ? extends Throwable> thenThrownBy(ThrowingCallableWithValue shouldRaiseThrowable) {
1333+
Object value;
1334+
try {
1335+
value = shouldRaiseThrowable.call();
1336+
} catch (Throwable throwable) {
1337+
return assertThat(throwable);
1338+
}
1339+
throw Failures.instance().failure(format("Expecting code to raise a throwable, but it returned [%s] instead", value));
1340+
}
1341+
13191342
/**
13201343
* Allows to capture and then assert on a {@link Throwable} like {@code thenThrownBy(ThrowingCallable)} but this method
13211344
* let you set the assertion description the same way you do with {@link AbstractAssert#as(String, Object...) as(String, Object...)}.
@@ -1353,6 +1376,26 @@ public static <T extends Throwable> AbstractThrowableAssert<?, T> then(T actual)
13531376
return assertThat(catchThrowable(shouldRaiseThrowable)).as(description, args).hasBeenThrown();
13541377
}
13551378

1379+
/**
1380+
* Similar to {@link #thenThrownBy(ThrowingCallable, String, Object...)}, but when the called code returns a value instead of
1381+
* throwing, the assertion error shows the returned value to help understand what went wrong.
1382+
*
1383+
* @param shouldRaiseThrowable The {@link ThrowingCallableWithValue} or lambda with the code that should raise the throwable.
1384+
* @return the created {@link ThrowableAssert}.
1385+
* @since 3.25.0
1386+
*/
1387+
@CanIgnoreReturnValue
1388+
public static AbstractThrowableAssert<?, ? extends Throwable> thenThrownBy(ThrowingCallableWithValue shouldRaiseThrowable,
1389+
String description, Object... args) {
1390+
Object value;
1391+
try {
1392+
value = shouldRaiseThrowable.call();
1393+
} catch (Throwable throwable) {
1394+
return assertThat(throwable).as(description, args);
1395+
}
1396+
throw Failures.instance().failure(format("Expecting code to raise a throwable, but it returned [%s] instead", value));
1397+
}
1398+
13561399
/**
13571400
* Allows to capture and then assert on a {@link Throwable} more easily when used with Java 8 lambdas.
13581401
*

assertj-core/src/main/java/org/assertj/core/api/ThrowableAssert.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ public interface ThrowingCallable {
3333
void call() throws Throwable;
3434
}
3535

36+
public interface ThrowingCallableWithValue {
37+
Object call() throws Throwable;
38+
}
39+
3640
public ThrowableAssert(ACTUAL actual) {
3741
super(actual, ThrowableAssert.class);
3842
}

assertj-core/src/test/java/org/assertj/core/api/throwable/ThrowableAssert_built_from_ThrowingCallable_Test.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
*/
1313
package org.assertj.core.api.throwable;
1414

15+
import static java.lang.String.format;
1516
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
1617
import static org.assertj.core.api.Assertions.assertThatThrownBy;
18+
import static org.assertj.core.util.AssertionsUtil.assertThatAssertionErrorIsThrownBy;
1719

1820
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
1921
import org.junit.jupiter.api.Test;
@@ -50,7 +52,14 @@ public void call() {
5052
// no exception
5153
}
5254
});
53-
}).withMessage(String.format("%nExpecting code to raise a throwable."));
55+
}).withMessage(format("%nExpecting code to raise a throwable."));
5456
}
5557

58+
@Test
59+
void should_fail_and_show_value_returned_by_callable_code() {
60+
// GIVEN
61+
ThrowingCallable code = () -> assertThatThrownBy(() -> 42);
62+
// WHEN/THEN
63+
assertThatAssertionErrorIsThrownBy(code).withMessage("Expecting code to raise a throwable, but it returned [42] instead");
64+
}
5665
}

assertj-core/src/test/java/org/assertj/core/api/throwable/ThrowableAssert_built_with_then_method_Test.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414

1515
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
1616
import static org.assertj.core.api.BDDAssertions.thenThrownBy;
17+
import static org.assertj.core.util.AssertionsUtil.assertThatAssertionErrorIsThrownBy;
1718

1819
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
1920
import org.junit.jupiter.api.Test;
2021

21-
// TODO build two throwable assert with then and assertThat and compare them.
2222
class ThrowableAssert_built_with_then_method_Test {
2323

2424
@Test
@@ -54,4 +54,11 @@ public void call() {
5454
}).withMessage(String.format("%nExpecting code to raise a throwable."));
5555
}
5656

57+
@Test
58+
void should_fail_if_value_is_returned_by_callable_code() {
59+
// GIVEN
60+
ThrowingCallable code = () -> thenThrownBy(() -> 42);
61+
// WHEN/THEN
62+
assertThatAssertionErrorIsThrownBy(code).withMessage("Expecting code to raise a throwable, but it returned [42] instead");
63+
}
5764
}

0 commit comments

Comments
 (0)