Skip to content

Commit 4b500d2

Browse files
Add map(…) and flatMap(…) to iterable assertions as aliases of extracting/flatExtracting.
Fixes #2023
1 parent 41a6c42 commit 4b500d2

9 files changed

+799
-262
lines changed

src/main/java/org/assertj/core/api/AbstractIterableAssert.java

Lines changed: 366 additions & 87 deletions
Large diffs are not rendered by default.

src/main/java/org/assertj/core/api/IterableAssert.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,16 +137,34 @@ public final <EXCEPTION extends Exception> AbstractListAssert<?, List<?>, Object
137137
return super.flatExtracting(extractors);
138138
}
139139

140+
@Override
141+
@SafeVarargs
142+
public final <EXCEPTION extends Exception> AbstractListAssert<?, List<? extends Object>, Object, ObjectAssert<Object>> flatMap(ThrowingExtractor<? super ELEMENT, ?, EXCEPTION>... mappers) {
143+
return super.flatMap(mappers);
144+
}
145+
140146
@Override
141147
@SafeVarargs
142148
public final AbstractListAssert<?, List<?>, Object, ObjectAssert<Object>> flatExtracting(Function<? super ELEMENT, ?>... extractors) {
143149
return super.flatExtracting(extractors);
144150
}
145-
151+
152+
@Override
153+
@SafeVarargs
154+
public final AbstractListAssert<?, List<? extends Object>, Object, ObjectAssert<Object>> flatMap(Function<? super ELEMENT, ?>... mappers) {
155+
return super.flatMap(mappers);
156+
}
157+
146158
@Override
147159
@SafeVarargs
148160
public final AbstractListAssert<?, List<? extends Tuple>, Tuple, ObjectAssert<Tuple>> extracting(Function<? super ELEMENT, ?>... extractors) {
149161
return super.extracting(extractors);
150162
}
151163

164+
@Override
165+
@SafeVarargs
166+
public final AbstractListAssert<?, List<? extends Tuple>, Tuple, ObjectAssert<Tuple>> map(Function<? super ELEMENT, ?>... mappers) {
167+
return super.extracting(mappers);
168+
}
169+
152170
}

src/main/java/org/assertj/core/api/ListAssert.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,16 +329,34 @@ public final AbstractListAssert<?, List<? extends Tuple>, Tuple, ObjectAssert<Tu
329329
return super.extracting(extractors);
330330
}
331331

332+
@Override
333+
@SafeVarargs
334+
public final AbstractListAssert<?, List<? extends Tuple>, Tuple, ObjectAssert<Tuple>> map(Function<? super ELEMENT, ?>... mappers) {
335+
return super.map(mappers);
336+
}
337+
332338
@Override
333339
@SafeVarargs
334340
public final <EXCEPTION extends Exception> AbstractListAssert<?, List<?>, Object, ObjectAssert<Object>> flatExtracting(ThrowingExtractor<? super ELEMENT, ?, EXCEPTION>... extractors) {
335341
return super.flatExtracting(extractors);
336342
}
337343

344+
@Override
345+
@SafeVarargs
346+
public final <EXCEPTION extends Exception> AbstractListAssert<?, List<? extends Object>, Object, ObjectAssert<Object>> flatMap(ThrowingExtractor<? super ELEMENT, ?, EXCEPTION>... mappers) {
347+
return super.flatMap(mappers);
348+
}
349+
338350
@Override
339351
@SafeVarargs
340352
public final AbstractListAssert<?, List<?>, Object, ObjectAssert<Object>> flatExtracting(Function<? super ELEMENT, ?>... extractors) {
341353
return super.flatExtracting(extractors);
342354
}
343355

356+
@Override
357+
@SafeVarargs
358+
public final AbstractListAssert<?, List<? extends Object>, Object, ObjectAssert<Object>> flatMap(Function<? super ELEMENT, ?>... mappers) {
359+
return super.flatMap(mappers);
360+
}
361+
344362
}

src/test/java/org/assertj/core/api/BDDSoftAssertionsTest.java

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,9 +1141,40 @@ void iterable_soft_assertions_should_report_errors_on_final_methods_and_methods_
11411141
.filteredOnAssertions(name -> assertThat(name.first).startsWith("Jo"))
11421142
.as("filteredOn with consumer")
11431143
.hasSize(5);
1144+
softly.then(characters)
1145+
.flatMap(childrenExtractor)
1146+
.as("using flatMap on Iterable")
1147+
.containsAnyOf(homer, fred);
1148+
softly.then(characters)
1149+
.flatMap(CartoonCharacter::getChildrenWithException)
1150+
.as("using flatMap on Iterable with exception")
1151+
.containsExactlyInAnyOrder(homer, fred);
1152+
softly.then(names)
1153+
.flatMap(firstNameFunction, lastNameFunction)
1154+
.as("flatMap with multiple Extractors")
1155+
.contains("John", "Jane", "Doe")
1156+
.contains("Sauron");
1157+
softly.then(names)
1158+
.flatMap(throwingFirstNameExtractor, throwingLastNameExtractor)
1159+
.as("flatMap with multiple ThrowingExtractors")
1160+
.contains("John", "Jane", "Doe")
1161+
.contains("Sauron");
1162+
softly.then(names)
1163+
.map(throwingFirstNameExtractor)
1164+
.as("map with ThrowingExtractor")
1165+
.contains("frodo");
1166+
softly.then(names)
1167+
.map(firstNameFunction)
1168+
.as("map with function")
1169+
.contains("sam");
1170+
softly.then(names)
1171+
.map(firstNameFunction, lastNameFunction)
1172+
.as("map with multiple functions")
1173+
.contains(tuple("John", "Doe"))
1174+
.contains(tuple("Frodo", "Baggins"));
11441175
// THEN
11451176
List<Throwable> errorsCollected = softly.errorsCollected();
1146-
assertThat(errorsCollected).hasSize(33);
1177+
assertThat(errorsCollected).hasSize(40);
11471178
assertThat(errorsCollected.get(0)).hasMessageContaining("gandalf");
11481179
assertThat(errorsCollected.get(1)).hasMessageContaining("frodo");
11491180
assertThat(errorsCollected.get(2)).hasMessageContaining("foo")
@@ -1178,6 +1209,13 @@ void iterable_soft_assertions_should_report_errors_on_final_methods_and_methods_
11781209
assertThat(errorsCollected.get(30)).hasMessageContaining("using flatExtracting(String... fieldOrPropertyNames)");
11791210
assertThat(errorsCollected.get(31)).hasMessageContaining("using flatExtracting(String fieldOrPropertyName)");
11801211
assertThat(errorsCollected.get(32)).hasMessageContaining("filteredOn with consumer");
1212+
assertThat(errorsCollected.get(33)).hasMessageContaining("using flatMap on Iterable");
1213+
assertThat(errorsCollected.get(34)).hasMessageContaining("using flatMap on Iterable with exception");
1214+
assertThat(errorsCollected.get(35)).hasMessageContaining("flatMap with multiple Extractors");
1215+
assertThat(errorsCollected.get(36)).hasMessageContaining("flatMap with multiple ThrowingExtractors");
1216+
assertThat(errorsCollected.get(37)).hasMessageContaining("map with ThrowingExtractor");
1217+
assertThat(errorsCollected.get(38)).hasMessageContaining("map with function");
1218+
assertThat(errorsCollected.get(39)).hasMessageContaining("map with multiple functions");
11811219
}
11821220

11831221
// the test would fail if any method was not proxyable as the assertion error would not be softly caught
@@ -1295,9 +1333,40 @@ void list_soft_assertions_should_report_errors_on_final_methods_and_methods_that
12951333
.filteredOnAssertions(name -> assertThat(name.first).startsWith("Jo"))
12961334
.as("filteredOn with consumer")
12971335
.hasSize(5);
1336+
softly.then(names)
1337+
.flatMap(firstNameFunction, lastNameFunction)
1338+
.as("flatMap with multiple Extractors")
1339+
.contains("John", "Jane", "Doe")
1340+
.contains("Sauron");
1341+
softly.then(names)
1342+
.flatMap(throwingFirstNameExtractor, throwingLastNameExtractor)
1343+
.as("flatMap with multiple ThrowingExtractors")
1344+
.contains("John", "Jane", "Doe")
1345+
.contains("Sauron");
1346+
softly.then(characters)
1347+
.flatMap(CartoonCharacter::getChildren)
1348+
.as("using flatMap on Iterable")
1349+
.containsAnyOf(homer, fred);
1350+
softly.then(characters)
1351+
.flatMap(CartoonCharacter::getChildrenWithException)
1352+
.as("using flatMap on Iterable with exception")
1353+
.containsExactlyInAnyOrder(homer, fred);
1354+
softly.then(names)
1355+
.map(throwingFirstNameExtractor)
1356+
.as("using map with ThrowingExtractor")
1357+
.contains("frodo");
1358+
softly.then(names)
1359+
.map(firstNameFunction)
1360+
.as("map with function")
1361+
.contains("sam");
1362+
softly.then(names)
1363+
.map(firstNameFunction, lastNameFunction)
1364+
.as("map with multiple functions")
1365+
.contains(tuple("John", "Doe"))
1366+
.contains(tuple("Frodo", "Baggins"));
12981367
// THEN
12991368
List<Throwable> errorsCollected = softly.errorsCollected();
1300-
assertThat(errorsCollected).hasSize(33);
1369+
assertThat(errorsCollected).hasSize(40);
13011370
assertThat(errorsCollected.get(0)).hasMessageContaining("gandalf");
13021371
assertThat(errorsCollected.get(1)).hasMessageContaining("frodo");
13031372
assertThat(errorsCollected.get(2)).hasMessageContaining("foo")
@@ -1332,6 +1401,13 @@ void list_soft_assertions_should_report_errors_on_final_methods_and_methods_that
13321401
assertThat(errorsCollected.get(30)).hasMessageContaining("using flatExtracting(String... fieldOrPropertyNames)");
13331402
assertThat(errorsCollected.get(31)).hasMessageContaining("using flatExtracting(String fieldOrPropertyName)");
13341403
assertThat(errorsCollected.get(32)).hasMessageContaining("filteredOn with consumer");
1404+
assertThat(errorsCollected.get(33)).hasMessageContaining("flatMap with multiple Extractors");
1405+
assertThat(errorsCollected.get(34)).hasMessageContaining("flatMap with multiple ThrowingExtractors");
1406+
assertThat(errorsCollected.get(35)).hasMessageContaining("using flatMap on Iterable");
1407+
assertThat(errorsCollected.get(36)).hasMessageContaining("using flatMap on Iterable with exception");
1408+
assertThat(errorsCollected.get(37)).hasMessageContaining("using map with ThrowingExtractor");
1409+
assertThat(errorsCollected.get(38)).hasMessageContaining("map with function");
1410+
assertThat(errorsCollected.get(39)).hasMessageContaining("map with multiple functions");
13351411
}
13361412

13371413
// the test would fail if any method was not proxyable as the assertion error would not be softly caught

src/test/java/org/assertj/core/api/SoftAssertionsTest.java

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,9 +1413,45 @@ void iterable_soft_assertions_should_report_errors_on_final_methods_and_methods_
14131413
.filteredOnAssertions(name -> assertThat(name.first).startsWith("Jo"))
14141414
.as("filteredOn with consumer")
14151415
.hasSize(5);
1416+
softly.assertThat(characters)
1417+
.as("using flatMap on Iterable")
1418+
.overridingErrorMessage("error message")
1419+
.flatMap(childrenExtractor)
1420+
.containsAnyOf(homer, fred);
1421+
softly.assertThat(characters)
1422+
.as("using flatMap on Iterable with exception")
1423+
.overridingErrorMessage("error message")
1424+
.flatMap(CartoonCharacter::getChildrenWithException)
1425+
.containsExactlyInAnyOrder(homer, fred);
1426+
softly.assertThat(names)
1427+
.overridingErrorMessage("error message")
1428+
.as("flatMap with multiple Extractors")
1429+
.flatMap(firstNameFunction, lastNameFunction)
1430+
.contains("John", "Jane", "Doe")
1431+
.contains("Sauron");
1432+
softly.assertThat(names)
1433+
.overridingErrorMessage("error message")
1434+
.as("flatMap with multiple ThrowingExtractors")
1435+
.flatMap(throwingFirstNameFunction, throwingLastNameFunction)
1436+
.contains("John", "Jane", "Doe")
1437+
.contains("Sauron");
1438+
softly.assertThat(names)
1439+
.as("map(throwingFirstNameFunction)")
1440+
.overridingErrorMessage("error message")
1441+
.map(throwingFirstNameFunction)
1442+
.contains("frodo");
1443+
softly.assertThat(names)
1444+
.as("map(firstNameFunction)")
1445+
.map(firstNameFunction)
1446+
.contains("sam");
1447+
softly.assertThat(names)
1448+
.map(firstNameFunction, lastNameFunction)
1449+
.as("map with multiple functions")
1450+
.contains(tuple("John", "Doe"))
1451+
.contains(tuple("Frodo", "Baggins"));
14161452
// THEN
14171453
List<Throwable> errorsCollected = softly.errorsCollected();
1418-
assertThat(errorsCollected).hasSize(33);
1454+
assertThat(errorsCollected).hasSize(40);
14191455
assertThat(errorsCollected.get(0)).hasMessage("[extracting(throwingFirstNameFunction)] error message");
14201456
assertThat(errorsCollected.get(1)).hasMessage("[extracting(throwingFirstNameFunction)] error message");
14211457
assertThat(errorsCollected.get(2)).hasMessage("[extracting(\"last\")] error message");
@@ -1449,6 +1485,13 @@ void iterable_soft_assertions_should_report_errors_on_final_methods_and_methods_
14491485
assertThat(errorsCollected.get(30)).hasMessage("[using flatExtracting(String... fieldOrPropertyNames)] error message");
14501486
assertThat(errorsCollected.get(31)).hasMessage("[using flatExtracting(String fieldOrPropertyName)] error message");
14511487
assertThat(errorsCollected.get(32)).hasMessage("[filteredOn with consumer] error message");
1488+
assertThat(errorsCollected.get(33)).hasMessageContaining("using flatMap on Iterable");
1489+
assertThat(errorsCollected.get(34)).hasMessageContaining("using flatMap on Iterable with exception");
1490+
assertThat(errorsCollected.get(35)).hasMessageContaining("flatMap with multiple Extractors");
1491+
assertThat(errorsCollected.get(36)).hasMessageContaining("flatMap with multiple ThrowingExtractors");
1492+
assertThat(errorsCollected.get(37)).hasMessageContaining("map(throwingFirstNameFunction)");
1493+
assertThat(errorsCollected.get(38)).hasMessageContaining("map(firstNameFunction)");
1494+
assertThat(errorsCollected.get(39)).hasMessageContaining("map with multiple functions");
14521495
}
14531496

14541497
// the test would fail if any method was not proxyable as the assertion error would not be softly caught
@@ -1597,9 +1640,45 @@ void list_soft_assertions_should_report_errors_on_final_methods_and_methods_that
15971640
.filteredOnAssertions(name -> assertThat(name.first).startsWith("Jo"))
15981641
.as("filteredOn with consumer")
15991642
.hasSize(5);
1643+
softly.assertThat(names)
1644+
.overridingErrorMessage("error message")
1645+
.as("flatMap with multiple Extractors")
1646+
.flatMap(firstNameFunction, lastNameFunction)
1647+
.contains("John", "Jane", "Doe")
1648+
.contains("Sauron");
1649+
softly.assertThat(names)
1650+
.overridingErrorMessage("error message")
1651+
.as("flatMap with multiple ThrowingExtractors")
1652+
.flatMap(throwingFirstNameFunction, throwingLastNameFunction)
1653+
.contains("John", "Jane", "Doe")
1654+
.contains("Sauron");
1655+
softly.assertThat(characters)
1656+
.as("using flatMap on Iterable")
1657+
.overridingErrorMessage("error message")
1658+
.flatMap(childrenExtractor)
1659+
.containsAnyOf(homer, fred);
1660+
softly.assertThat(characters)
1661+
.as("using flatMap on Iterable with exception")
1662+
.overridingErrorMessage("error message")
1663+
.flatMap(CartoonCharacter::getChildrenWithException)
1664+
.containsExactlyInAnyOrder(homer, fred);
1665+
softly.assertThat(names)
1666+
.as("map(throwingFirstNameFunction)")
1667+
.overridingErrorMessage("error message")
1668+
.map(throwingFirstNameFunction)
1669+
.contains("frodo");
1670+
softly.assertThat(names)
1671+
.as("map(firstNameFunction)")
1672+
.map(firstNameFunction)
1673+
.contains("sam");
1674+
softly.assertThat(names)
1675+
.map(firstNameFunction, lastNameFunction)
1676+
.as("map with multiple functions")
1677+
.contains(tuple("John", "Doe"))
1678+
.contains(tuple("Frodo", "Baggins"));
16001679
// THEN
16011680
List<Throwable> errorsCollected = softly.errorsCollected();
1602-
assertThat(errorsCollected).hasSize(33);
1681+
assertThat(errorsCollected).hasSize(40);
16031682
assertThat(errorsCollected.get(0)).hasMessage("[extracting(throwingFirstNameFunction)] error message");
16041683
assertThat(errorsCollected.get(1)).hasMessage("[extracting(throwingFirstNameFunction)] error message");
16051684
assertThat(errorsCollected.get(2)).hasMessage("[extracting(\"last\")] error message");
@@ -1633,6 +1712,13 @@ void list_soft_assertions_should_report_errors_on_final_methods_and_methods_that
16331712
assertThat(errorsCollected.get(30)).hasMessage("[using flatExtracting(String... fieldOrPropertyNames)] error message");
16341713
assertThat(errorsCollected.get(31)).hasMessage("[using flatExtracting(String fieldOrPropertyName)] error message");
16351714
assertThat(errorsCollected.get(32)).hasMessage("[filteredOn with consumer] error message");
1715+
assertThat(errorsCollected.get(33)).hasMessageContaining("flatMap with multiple Extractors");
1716+
assertThat(errorsCollected.get(34)).hasMessageContaining("flatMap with multiple ThrowingExtractors");
1717+
assertThat(errorsCollected.get(35)).hasMessageContaining("using flatMap on Iterable");
1718+
assertThat(errorsCollected.get(36)).hasMessageContaining("using flatMap on Iterable with exception");
1719+
assertThat(errorsCollected.get(37)).hasMessageContaining("map(throwingFirstNameFunction)");
1720+
assertThat(errorsCollected.get(38)).hasMessageContaining("map(firstNameFunction)");
1721+
assertThat(errorsCollected.get(39)).hasMessageContaining("map with multiple functions");
16361722
}
16371723

16381724
// the test would fail if any method was not proxyable as the assertion error would not be softly caught

src/test/java/org/assertj/core/api/assumptions/Assumptions_assumeThat_with_various_java_8_types_Test.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
import static java.util.concurrent.CompletableFuture.completedFuture;
1616
import static org.assertj.core.api.Assertions.assertThatCode;
17-
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
1817
import static org.assertj.core.api.Assumptions.assumeThat;
1918
import static org.assertj.core.api.Assumptions.assumeThatCode;
2019
import static org.assertj.core.util.AssertionsUtil.expectAssumptionNotMetException;
@@ -44,7 +43,6 @@
4443
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
4544
import org.junit.jupiter.params.ParameterizedTest;
4645
import org.junit.jupiter.params.provider.MethodSource;
47-
import org.opentest4j.TestAbortedException;
4846

4947
class Assumptions_assumeThat_with_various_java_8_types_Test {
5048

src/test/java/org/assertj/core/api/assumptions/BaseAssumptionsRunnerTest.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import static org.assertj.core.api.Assertions.assertThatCode;
1616
import static org.assertj.core.util.AssertionsUtil.expectAssumptionNotMetException;
1717

18-
import java.util.Collection;
1918
import java.util.function.Function;
2019

2120
import org.assertj.core.api.Assertions;
@@ -49,7 +48,6 @@ public abstract class BaseAssumptionsRunnerTest {
4948
protected static Function<? super TolkienCharacter, Integer> ageExtractor;
5049
protected static Function<TolkienCharacter, String> nameExtractorFunction;
5150
protected static Function<TolkienCharacter, Integer> ageExtractorFunction;
52-
protected static Function<? super CartoonCharacter, ? extends Collection<CartoonCharacter>> childrenExtractor;
5351

5452
private static void setupData() {
5553
bart = new CartoonCharacter("Bart Simpson");
@@ -74,7 +72,6 @@ private static void setupData() {
7472

7573
frodo = TolkienCharacter.of("Frodo", 33, Race.HOBBIT);
7674
sam = TolkienCharacter.of("Sam", 35, Race.HOBBIT);
77-
childrenExtractor = CartoonCharacter::getChildren;
7875
}
7976

8077
@ParameterizedTest

0 commit comments

Comments
 (0)