Skip to content

Commit d51cfd9

Browse files
committed
Remove elements by reference in assertSatisfiesExactlyInAnyOrder
Fixes #3339.
1 parent 7f786bd commit d51cfd9

File tree

3 files changed

+55
-20
lines changed

3 files changed

+55
-20
lines changed

assertj-core/src/main/java/org/assertj/core/internal/ElementsSatisfyingConsumer.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
package org.assertj.core.internal;
1414

1515
import static java.util.stream.Collectors.toList;
16+
import static java.util.stream.IntStream.range;
1617
import static org.assertj.core.internal.Iterables.byPassingAssertions;
1718
import static org.assertj.core.util.Streams.stream;
1819

@@ -28,12 +29,17 @@
2829
* @param <E> element type
2930
*/
3031
class ElementsSatisfyingConsumer<E> {
32+
3133
private final List<E> elements;
3234

3335
ElementsSatisfyingConsumer(Iterable<? extends E> actual, Consumer<? super E> assertions) {
3436
this(filterByPassingAssertions(actual, assertions));
3537
}
3638

39+
private static <E> List<E> filterByPassingAssertions(Iterable<? extends E> actual, Consumer<? super E> assertions) {
40+
return stream(actual).filter(byPassingAssertions(assertions)).collect(toList());
41+
}
42+
3743
private ElementsSatisfyingConsumer(List<E> elements) {
3844
this.elements = elements;
3945
}
@@ -43,7 +49,7 @@ List<E> getElements() {
4349
}
4450

4551
/**
46-
* New <code>ElementsSatisfyingConsumer</code> containing all elements except the (first occurrence of the) given element.
52+
* New <code>ElementsSatisfyingConsumer</code> containing all elements except the first occurrence of the given element.
4753
*
4854
* <p> This instance is not modified.
4955
*
@@ -52,11 +58,14 @@ List<E> getElements() {
5258
*/
5359
ElementsSatisfyingConsumer<E> withoutElement(E element) {
5460
ArrayList<E> listWithoutElement = new ArrayList<>(elements);
55-
listWithoutElement.remove(element);
61+
removeFirstReference(element, listWithoutElement);
5662
return new ElementsSatisfyingConsumer<>(listWithoutElement);
5763
}
5864

59-
private static <E> List<E> filterByPassingAssertions(Iterable<? extends E> actual, Consumer<? super E> assertions) {
60-
return stream(actual).filter(byPassingAssertions(assertions)).collect(toList());
65+
private static void removeFirstReference(Object element, List<?> elements) {
66+
range(0, elements.size()).filter(i -> elements.get(i) == element)
67+
.findFirst()
68+
.ifPresent(elements::remove);
6169
}
70+
6271
}

assertj-core/src/main/java/org/assertj/core/internal/Iterables.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ public void assertContainsOnlyNulls(AssertionInfo info, Iterable<?> actual) {
461461
if (sizeOf(actual) == 0) throw failures.failure(info, shouldContainOnlyNulls(actual));
462462
// look for any non-null elements
463463
List<Object> nonNullElements = stream(actual).filter(java.util.Objects::nonNull).collect(toList());
464-
if (nonNullElements.size() > 0) throw failures.failure(info, shouldContainOnlyNulls(actual, nonNullElements));
464+
if (!nonNullElements.isEmpty()) throw failures.failure(info, shouldContainOnlyNulls(actual, nonNullElements));
465465
}
466466

467467
/**
@@ -623,7 +623,7 @@ public void assertIsSubsetOf(AssertionInfo info, Iterable<?> actual, Iterable<?>
623623
checkIterableIsNotNull(values);
624624
List<Object> extra = stream(actual).filter(actualElement -> !iterableContains(values, actualElement))
625625
.collect(toList());
626-
if (extra.size() > 0) throw failures.failure(info, shouldBeSubsetOf(actual, values, extra, comparisonStrategy));
626+
if (!extra.isEmpty()) throw failures.failure(info, shouldBeSubsetOf(actual, values, extra, comparisonStrategy));
627627
}
628628

629629
/**
@@ -1253,7 +1253,7 @@ private static <E> boolean areAllConsumersSatisfied(Queue<ElementsSatisfyingCons
12531253
// recursively test whether we can find any specific matching permutation that can meet the requirements
12541254
if (satisfiedElementsPerConsumer.isEmpty()) return true; // all consumers have been satisfied
12551255

1256-
// pop the head (i.e, elements satisfying the current consumer), process the tail (i.e., remaining consumers)...
1256+
// pop the head (i.e., elements satisfying the current consumer), process the tail (i.e., remaining consumers)...
12571257
ElementsSatisfyingConsumer<E> head = satisfiedElementsPerConsumer.remove();
12581258
List<E> elementsSatisfyingCurrentConsumer = head.getElements();
12591259
if (elementsSatisfyingCurrentConsumer.isEmpty()) return false; // no element satisfies current consumer
@@ -1335,7 +1335,7 @@ public <E> void assertNoneSatisfy(AssertionInfo info, Iterable<? extends E> actu
13351335
.filter(Optional::isPresent)
13361336
.map(Optional::get)
13371337
.collect(toList());
1338-
if (erroneousElements.size() > 0) throw failures.failure(info, noElementsShouldSatisfy(actual, erroneousElements));
1338+
if (!erroneousElements.isEmpty()) throw failures.failure(info, noElementsShouldSatisfy(actual, erroneousElements));
13391339
}
13401340

13411341
private <E> Optional<E> failsRestrictions(E element, Consumer<? super E> restrictions) {

assertj-core/src/test/java/org/assertj/core/internal/iterables/Iterables_assertSatisfiesExactlyInAnyOrder_Test.java

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,13 @@
2525
import java.util.List;
2626
import java.util.function.Consumer;
2727

28-
import org.assertj.core.api.AssertionInfo;
29-
import org.assertj.core.internal.Iterables;
3028
import org.assertj.core.internal.IterablesBaseTest;
31-
import org.junit.jupiter.api.DisplayName;
29+
import org.assertj.core.test.Jedi;
3230
import org.junit.jupiter.api.Test;
3331

3432
/**
35-
* Tests for <code>{@link Iterables#assertSatisfiesExactlyInAnyOrder(AssertionInfo, Iterable, Consumer[])}</code>.
36-
*
3733
* @author Ting Sun
3834
*/
39-
@DisplayName("Iterables assertSatisfiesExactlyInAnyOrder")
4035
class Iterables_assertSatisfiesExactlyInAnyOrder_Test extends IterablesBaseTest {
4136

4237
private List<String> actual = newArrayList("Luke", "Leia", "Yoda");
@@ -50,7 +45,6 @@ void should_pass_if_all_consumers_are_satisfied_by_different_elements_in_order()
5045
assertThat(s).hasSize(4);
5146
assertThat(s).doesNotContain("L");
5247
}; // Matches "Yoda"
53-
5448
// WHEN/THEN
5549
iterables.assertSatisfiesExactlyInAnyOrder(info, actual, array(consumer1, consumer2, consumer3));
5650
}
@@ -61,7 +55,6 @@ void should_pass_if_all_consumers_are_satisfied_by_different_elements_in_any_ord
6155
Consumer<String> consumer1 = s -> assertThat(s).contains("Y"); // Matches "Yoda"
6256
Consumer<String> consumer2 = s -> assertThat(s).contains("L"); // Matches "Luke" and "Leia"
6357
Consumer<String> consumer3 = s -> assertThat(s).doesNotContain("a"); // Matches "Luke"
64-
6558
// WHEN/THEN
6659
iterables.assertSatisfiesExactlyInAnyOrder(info, actual, array(consumer1, consumer2, consumer3));
6760
iterables.assertSatisfiesExactlyInAnyOrder(info, actual, array(consumer1, consumer3, consumer2));
@@ -82,7 +75,6 @@ void should_fail_if_one_of_the_consumer_cannot_be_satisfied() {
8275
array(consumer1,
8376
consumer2,
8477
consumer3)));
85-
8678
// THEN
8779
then(assertionError).hasMessage(shouldSatisfyExactlyInAnyOrder(actual).create());
8880
}
@@ -118,12 +110,12 @@ void should_fail_if_one_of_the_requirements_cannot_be_satisfied() {
118110
}
119111

120112
@Test
121-
void should_pass_if_iterable_contains_multiple_equal_elements() {
113+
void should_pass_if_iterable_contains_same_elements() {
122114
// GIVEN
123-
List<String> names = newArrayList("Luke", "Luke");
115+
String luke = "Luke";
116+
List<String> names = newArrayList(luke, luke);
124117
Consumer<String> consumer1 = s -> assertThat(s).contains("L");
125118
Consumer<String> consumer2 = s -> assertThat(s).contains("u");
126-
127119
// WHEN/THEN
128120
iterables.assertSatisfiesExactlyInAnyOrder(info, names, array(consumer1, consumer2));
129121
}
@@ -186,4 +178,38 @@ void should_fail_if_there_are_too_many_consumers() {
186178
then(assertionError).hasMessage(shouldHaveSize(actual, 3, 4).create());
187179
}
188180

181+
@Test
182+
void should_pass_without_relying_on_elements_equality() {
183+
// GIVEN
184+
List<Jedi> actual = newArrayList(new JediOverridingEquals("Luke", "blue"),
185+
new JediOverridingEquals("Luke", "green"),
186+
new JediOverridingEquals("Luke", "green"));
187+
Consumer<Jedi>[] consumers = array(jedi -> assertThat(jedi.lightSaberColor).isEqualTo("green"),
188+
jedi -> assertThat(jedi.lightSaberColor).isEqualTo("blue"),
189+
jedi -> assertThat(jedi.lightSaberColor).isEqualTo("green"));
190+
// WHEN/THEN
191+
iterables.assertSatisfiesExactlyInAnyOrder(info, actual, consumers);
192+
}
193+
194+
private static class JediOverridingEquals extends Jedi {
195+
196+
private JediOverridingEquals(String name, String lightSaberColor) {
197+
super(name, lightSaberColor);
198+
}
199+
200+
@Override
201+
public boolean equals(Object o) {
202+
if (this == o) return true;
203+
if (o == null || getClass() != o.getClass()) return false;
204+
JediOverridingEquals jedi = (JediOverridingEquals) o;
205+
return getName().equals(jedi.getName());
206+
}
207+
208+
@Override
209+
public int hashCode() {
210+
return getName().hashCode();
211+
}
212+
213+
}
214+
189215
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy