Skip to content

Commit

Permalink
Add map(…) and flatMap(…) to iterable assertions as aliases of extrac…
Browse files Browse the repository at this point in the history
…ting/flatExtracting.

Fixes #2023
  • Loading branch information
joel-costigliola committed Nov 6, 2020
1 parent 41a6c42 commit 4b500d2
Show file tree
Hide file tree
Showing 9 changed files with 799 additions and 262 deletions.
453 changes: 366 additions & 87 deletions src/main/java/org/assertj/core/api/AbstractIterableAssert.java

Large diffs are not rendered by default.

20 changes: 19 additions & 1 deletion src/main/java/org/assertj/core/api/IterableAssert.java
Original file line number Diff line number Diff line change
Expand Up @@ -137,16 +137,34 @@ public final <EXCEPTION extends Exception> AbstractListAssert<?, List<?>, Object
return super.flatExtracting(extractors);
}

@Override
@SafeVarargs
public final <EXCEPTION extends Exception> AbstractListAssert<?, List<? extends Object>, Object, ObjectAssert<Object>> flatMap(ThrowingExtractor<? super ELEMENT, ?, EXCEPTION>... mappers) {
return super.flatMap(mappers);
}

@Override
@SafeVarargs
public final AbstractListAssert<?, List<?>, Object, ObjectAssert<Object>> flatExtracting(Function<? super ELEMENT, ?>... extractors) {
return super.flatExtracting(extractors);
}


@Override
@SafeVarargs
public final AbstractListAssert<?, List<? extends Object>, Object, ObjectAssert<Object>> flatMap(Function<? super ELEMENT, ?>... mappers) {
return super.flatMap(mappers);
}

@Override
@SafeVarargs
public final AbstractListAssert<?, List<? extends Tuple>, Tuple, ObjectAssert<Tuple>> extracting(Function<? super ELEMENT, ?>... extractors) {
return super.extracting(extractors);
}

@Override
@SafeVarargs
public final AbstractListAssert<?, List<? extends Tuple>, Tuple, ObjectAssert<Tuple>> map(Function<? super ELEMENT, ?>... mappers) {
return super.extracting(mappers);
}

}
18 changes: 18 additions & 0 deletions src/main/java/org/assertj/core/api/ListAssert.java
Original file line number Diff line number Diff line change
Expand Up @@ -329,16 +329,34 @@ public final AbstractListAssert<?, List<? extends Tuple>, Tuple, ObjectAssert<Tu
return super.extracting(extractors);
}

@Override
@SafeVarargs
public final AbstractListAssert<?, List<? extends Tuple>, Tuple, ObjectAssert<Tuple>> map(Function<? super ELEMENT, ?>... mappers) {
return super.map(mappers);
}

@Override
@SafeVarargs
public final <EXCEPTION extends Exception> AbstractListAssert<?, List<?>, Object, ObjectAssert<Object>> flatExtracting(ThrowingExtractor<? super ELEMENT, ?, EXCEPTION>... extractors) {
return super.flatExtracting(extractors);
}

@Override
@SafeVarargs
public final <EXCEPTION extends Exception> AbstractListAssert<?, List<? extends Object>, Object, ObjectAssert<Object>> flatMap(ThrowingExtractor<? super ELEMENT, ?, EXCEPTION>... mappers) {
return super.flatMap(mappers);
}

@Override
@SafeVarargs
public final AbstractListAssert<?, List<?>, Object, ObjectAssert<Object>> flatExtracting(Function<? super ELEMENT, ?>... extractors) {
return super.flatExtracting(extractors);
}

@Override
@SafeVarargs
public final AbstractListAssert<?, List<? extends Object>, Object, ObjectAssert<Object>> flatMap(Function<? super ELEMENT, ?>... mappers) {
return super.flatMap(mappers);
}

}
80 changes: 78 additions & 2 deletions src/test/java/org/assertj/core/api/BDDSoftAssertionsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1141,9 +1141,40 @@ void iterable_soft_assertions_should_report_errors_on_final_methods_and_methods_
.filteredOnAssertions(name -> assertThat(name.first).startsWith("Jo"))
.as("filteredOn with consumer")
.hasSize(5);
softly.then(characters)
.flatMap(childrenExtractor)
.as("using flatMap on Iterable")
.containsAnyOf(homer, fred);
softly.then(characters)
.flatMap(CartoonCharacter::getChildrenWithException)
.as("using flatMap on Iterable with exception")
.containsExactlyInAnyOrder(homer, fred);
softly.then(names)
.flatMap(firstNameFunction, lastNameFunction)
.as("flatMap with multiple Extractors")
.contains("John", "Jane", "Doe")
.contains("Sauron");
softly.then(names)
.flatMap(throwingFirstNameExtractor, throwingLastNameExtractor)
.as("flatMap with multiple ThrowingExtractors")
.contains("John", "Jane", "Doe")
.contains("Sauron");
softly.then(names)
.map(throwingFirstNameExtractor)
.as("map with ThrowingExtractor")
.contains("frodo");
softly.then(names)
.map(firstNameFunction)
.as("map with function")
.contains("sam");
softly.then(names)
.map(firstNameFunction, lastNameFunction)
.as("map with multiple functions")
.contains(tuple("John", "Doe"))
.contains(tuple("Frodo", "Baggins"));
// THEN
List<Throwable> errorsCollected = softly.errorsCollected();
assertThat(errorsCollected).hasSize(33);
assertThat(errorsCollected).hasSize(40);
assertThat(errorsCollected.get(0)).hasMessageContaining("gandalf");
assertThat(errorsCollected.get(1)).hasMessageContaining("frodo");
assertThat(errorsCollected.get(2)).hasMessageContaining("foo")
Expand Down Expand Up @@ -1178,6 +1209,13 @@ void iterable_soft_assertions_should_report_errors_on_final_methods_and_methods_
assertThat(errorsCollected.get(30)).hasMessageContaining("using flatExtracting(String... fieldOrPropertyNames)");
assertThat(errorsCollected.get(31)).hasMessageContaining("using flatExtracting(String fieldOrPropertyName)");
assertThat(errorsCollected.get(32)).hasMessageContaining("filteredOn with consumer");
assertThat(errorsCollected.get(33)).hasMessageContaining("using flatMap on Iterable");
assertThat(errorsCollected.get(34)).hasMessageContaining("using flatMap on Iterable with exception");
assertThat(errorsCollected.get(35)).hasMessageContaining("flatMap with multiple Extractors");
assertThat(errorsCollected.get(36)).hasMessageContaining("flatMap with multiple ThrowingExtractors");
assertThat(errorsCollected.get(37)).hasMessageContaining("map with ThrowingExtractor");
assertThat(errorsCollected.get(38)).hasMessageContaining("map with function");
assertThat(errorsCollected.get(39)).hasMessageContaining("map with multiple functions");
}

// the test would fail if any method was not proxyable as the assertion error would not be softly caught
Expand Down Expand Up @@ -1295,9 +1333,40 @@ void list_soft_assertions_should_report_errors_on_final_methods_and_methods_that
.filteredOnAssertions(name -> assertThat(name.first).startsWith("Jo"))
.as("filteredOn with consumer")
.hasSize(5);
softly.then(names)
.flatMap(firstNameFunction, lastNameFunction)
.as("flatMap with multiple Extractors")
.contains("John", "Jane", "Doe")
.contains("Sauron");
softly.then(names)
.flatMap(throwingFirstNameExtractor, throwingLastNameExtractor)
.as("flatMap with multiple ThrowingExtractors")
.contains("John", "Jane", "Doe")
.contains("Sauron");
softly.then(characters)
.flatMap(CartoonCharacter::getChildren)
.as("using flatMap on Iterable")
.containsAnyOf(homer, fred);
softly.then(characters)
.flatMap(CartoonCharacter::getChildrenWithException)
.as("using flatMap on Iterable with exception")
.containsExactlyInAnyOrder(homer, fred);
softly.then(names)
.map(throwingFirstNameExtractor)
.as("using map with ThrowingExtractor")
.contains("frodo");
softly.then(names)
.map(firstNameFunction)
.as("map with function")
.contains("sam");
softly.then(names)
.map(firstNameFunction, lastNameFunction)
.as("map with multiple functions")
.contains(tuple("John", "Doe"))
.contains(tuple("Frodo", "Baggins"));
// THEN
List<Throwable> errorsCollected = softly.errorsCollected();
assertThat(errorsCollected).hasSize(33);
assertThat(errorsCollected).hasSize(40);
assertThat(errorsCollected.get(0)).hasMessageContaining("gandalf");
assertThat(errorsCollected.get(1)).hasMessageContaining("frodo");
assertThat(errorsCollected.get(2)).hasMessageContaining("foo")
Expand Down Expand Up @@ -1332,6 +1401,13 @@ void list_soft_assertions_should_report_errors_on_final_methods_and_methods_that
assertThat(errorsCollected.get(30)).hasMessageContaining("using flatExtracting(String... fieldOrPropertyNames)");
assertThat(errorsCollected.get(31)).hasMessageContaining("using flatExtracting(String fieldOrPropertyName)");
assertThat(errorsCollected.get(32)).hasMessageContaining("filteredOn with consumer");
assertThat(errorsCollected.get(33)).hasMessageContaining("flatMap with multiple Extractors");
assertThat(errorsCollected.get(34)).hasMessageContaining("flatMap with multiple ThrowingExtractors");
assertThat(errorsCollected.get(35)).hasMessageContaining("using flatMap on Iterable");
assertThat(errorsCollected.get(36)).hasMessageContaining("using flatMap on Iterable with exception");
assertThat(errorsCollected.get(37)).hasMessageContaining("using map with ThrowingExtractor");
assertThat(errorsCollected.get(38)).hasMessageContaining("map with function");
assertThat(errorsCollected.get(39)).hasMessageContaining("map with multiple functions");
}

// the test would fail if any method was not proxyable as the assertion error would not be softly caught
Expand Down
90 changes: 88 additions & 2 deletions src/test/java/org/assertj/core/api/SoftAssertionsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1413,9 +1413,45 @@ void iterable_soft_assertions_should_report_errors_on_final_methods_and_methods_
.filteredOnAssertions(name -> assertThat(name.first).startsWith("Jo"))
.as("filteredOn with consumer")
.hasSize(5);
softly.assertThat(characters)
.as("using flatMap on Iterable")
.overridingErrorMessage("error message")
.flatMap(childrenExtractor)
.containsAnyOf(homer, fred);
softly.assertThat(characters)
.as("using flatMap on Iterable with exception")
.overridingErrorMessage("error message")
.flatMap(CartoonCharacter::getChildrenWithException)
.containsExactlyInAnyOrder(homer, fred);
softly.assertThat(names)
.overridingErrorMessage("error message")
.as("flatMap with multiple Extractors")
.flatMap(firstNameFunction, lastNameFunction)
.contains("John", "Jane", "Doe")
.contains("Sauron");
softly.assertThat(names)
.overridingErrorMessage("error message")
.as("flatMap with multiple ThrowingExtractors")
.flatMap(throwingFirstNameFunction, throwingLastNameFunction)
.contains("John", "Jane", "Doe")
.contains("Sauron");
softly.assertThat(names)
.as("map(throwingFirstNameFunction)")
.overridingErrorMessage("error message")
.map(throwingFirstNameFunction)
.contains("frodo");
softly.assertThat(names)
.as("map(firstNameFunction)")
.map(firstNameFunction)
.contains("sam");
softly.assertThat(names)
.map(firstNameFunction, lastNameFunction)
.as("map with multiple functions")
.contains(tuple("John", "Doe"))
.contains(tuple("Frodo", "Baggins"));
// THEN
List<Throwable> errorsCollected = softly.errorsCollected();
assertThat(errorsCollected).hasSize(33);
assertThat(errorsCollected).hasSize(40);
assertThat(errorsCollected.get(0)).hasMessage("[extracting(throwingFirstNameFunction)] error message");
assertThat(errorsCollected.get(1)).hasMessage("[extracting(throwingFirstNameFunction)] error message");
assertThat(errorsCollected.get(2)).hasMessage("[extracting(\"last\")] error message");
Expand Down Expand Up @@ -1449,6 +1485,13 @@ void iterable_soft_assertions_should_report_errors_on_final_methods_and_methods_
assertThat(errorsCollected.get(30)).hasMessage("[using flatExtracting(String... fieldOrPropertyNames)] error message");
assertThat(errorsCollected.get(31)).hasMessage("[using flatExtracting(String fieldOrPropertyName)] error message");
assertThat(errorsCollected.get(32)).hasMessage("[filteredOn with consumer] error message");
assertThat(errorsCollected.get(33)).hasMessageContaining("using flatMap on Iterable");
assertThat(errorsCollected.get(34)).hasMessageContaining("using flatMap on Iterable with exception");
assertThat(errorsCollected.get(35)).hasMessageContaining("flatMap with multiple Extractors");
assertThat(errorsCollected.get(36)).hasMessageContaining("flatMap with multiple ThrowingExtractors");
assertThat(errorsCollected.get(37)).hasMessageContaining("map(throwingFirstNameFunction)");
assertThat(errorsCollected.get(38)).hasMessageContaining("map(firstNameFunction)");
assertThat(errorsCollected.get(39)).hasMessageContaining("map with multiple functions");
}

// the test would fail if any method was not proxyable as the assertion error would not be softly caught
Expand Down Expand Up @@ -1597,9 +1640,45 @@ void list_soft_assertions_should_report_errors_on_final_methods_and_methods_that
.filteredOnAssertions(name -> assertThat(name.first).startsWith("Jo"))
.as("filteredOn with consumer")
.hasSize(5);
softly.assertThat(names)
.overridingErrorMessage("error message")
.as("flatMap with multiple Extractors")
.flatMap(firstNameFunction, lastNameFunction)
.contains("John", "Jane", "Doe")
.contains("Sauron");
softly.assertThat(names)
.overridingErrorMessage("error message")
.as("flatMap with multiple ThrowingExtractors")
.flatMap(throwingFirstNameFunction, throwingLastNameFunction)
.contains("John", "Jane", "Doe")
.contains("Sauron");
softly.assertThat(characters)
.as("using flatMap on Iterable")
.overridingErrorMessage("error message")
.flatMap(childrenExtractor)
.containsAnyOf(homer, fred);
softly.assertThat(characters)
.as("using flatMap on Iterable with exception")
.overridingErrorMessage("error message")
.flatMap(CartoonCharacter::getChildrenWithException)
.containsExactlyInAnyOrder(homer, fred);
softly.assertThat(names)
.as("map(throwingFirstNameFunction)")
.overridingErrorMessage("error message")
.map(throwingFirstNameFunction)
.contains("frodo");
softly.assertThat(names)
.as("map(firstNameFunction)")
.map(firstNameFunction)
.contains("sam");
softly.assertThat(names)
.map(firstNameFunction, lastNameFunction)
.as("map with multiple functions")
.contains(tuple("John", "Doe"))
.contains(tuple("Frodo", "Baggins"));
// THEN
List<Throwable> errorsCollected = softly.errorsCollected();
assertThat(errorsCollected).hasSize(33);
assertThat(errorsCollected).hasSize(40);
assertThat(errorsCollected.get(0)).hasMessage("[extracting(throwingFirstNameFunction)] error message");
assertThat(errorsCollected.get(1)).hasMessage("[extracting(throwingFirstNameFunction)] error message");
assertThat(errorsCollected.get(2)).hasMessage("[extracting(\"last\")] error message");
Expand Down Expand Up @@ -1633,6 +1712,13 @@ void list_soft_assertions_should_report_errors_on_final_methods_and_methods_that
assertThat(errorsCollected.get(30)).hasMessage("[using flatExtracting(String... fieldOrPropertyNames)] error message");
assertThat(errorsCollected.get(31)).hasMessage("[using flatExtracting(String fieldOrPropertyName)] error message");
assertThat(errorsCollected.get(32)).hasMessage("[filteredOn with consumer] error message");
assertThat(errorsCollected.get(33)).hasMessageContaining("flatMap with multiple Extractors");
assertThat(errorsCollected.get(34)).hasMessageContaining("flatMap with multiple ThrowingExtractors");
assertThat(errorsCollected.get(35)).hasMessageContaining("using flatMap on Iterable");
assertThat(errorsCollected.get(36)).hasMessageContaining("using flatMap on Iterable with exception");
assertThat(errorsCollected.get(37)).hasMessageContaining("map(throwingFirstNameFunction)");
assertThat(errorsCollected.get(38)).hasMessageContaining("map(firstNameFunction)");
assertThat(errorsCollected.get(39)).hasMessageContaining("map with multiple functions");
}

// the test would fail if any method was not proxyable as the assertion error would not be softly caught
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

import static java.util.concurrent.CompletableFuture.completedFuture;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assumptions.assumeThat;
import static org.assertj.core.api.Assumptions.assumeThatCode;
import static org.assertj.core.util.AssertionsUtil.expectAssumptionNotMetException;
Expand Down Expand Up @@ -44,7 +43,6 @@
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.opentest4j.TestAbortedException;

class Assumptions_assumeThat_with_various_java_8_types_Test {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.util.AssertionsUtil.expectAssumptionNotMetException;

import java.util.Collection;
import java.util.function.Function;

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

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

frodo = TolkienCharacter.of("Frodo", 33, Race.HOBBIT);
sam = TolkienCharacter.of("Sam", 35, Race.HOBBIT);
childrenExtractor = CartoonCharacter::getChildren;
}

@ParameterizedTest
Expand Down
Loading

0 comments on commit 4b500d2

Please sign in to comment.