containsInAnyOrder incorrectly identifies differences in identical collections
luskentyre-green opened this issue · comments
When comparing two Lists or sets of characters, containsInOrder will report that a character is missing even when they sets or lists contain the same elements.
Code to reproduce: (hamcrest 2.2 plus JUnit 5)
package hamcrest.test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.is;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.Test;
class HamcrestTest {
@Test
void testTwoIdenticalSets() {
Set<Character> testSetOne = new HashSet<>(Arrays.asList('!', '$', '-', '=', '+', '*'));
Set<Character> testSetTwo = new HashSet<>(testSetOne);
assertThat(testSetOne.containsAll(testSetTwo), is(true));
// This assertion will fail, claiming that testSetOne does not contain '!'
assertThat(testSetOne, containsInAnyOrder(testSetTwo));
}
@Test
void testTwoIdenticalLists() {
List<Character> testSetOne = new ArrayList<>(Arrays.asList('%', '$', '-', '=', '+', '*'));
List<Character> testSetTwo = new ArrayList<>(testSetOne);
assertThat(testSetOne.containsAll(testSetTwo), is(true));
// This assertion will fail, claiming that testSetOne does not contain '%'
assertThat(testSetOne, containsInAnyOrder(testSetTwo));
}
}
output:
java.lang.AssertionError:
Expected: iterable with items [<[!, $, *, +, -, =]>] in any order
but: not matched: "!"
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:6)
java.lang.AssertionError:
Expected: iterable with items [<[%, $, -, =, +, *]>] in any order
but: not matched: "%"
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:6)
I suspect this is because there is no containsInAnyOrder(..)
accepting a collection of the actual items to match, but there is an overload accepting a collection with matchers for every element which needs to match.
So e.g. in the example with the sets, you are in fact asserting that testSetOne
must contain exactly one element, and that single element should be testSetTwo
. The code is invoking the T ...
vararg overload with one argument.