可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
That should be really simple question I believe. But somehow I can't find answer in Google.
Assume that I have 2 Lists of Strings. First contains "String A" and "String B", second one contains "String B" and "String A" (notice difference in order). I want to test them with JUnit to check whether they contains exactly the same Strings.
Is there any assert that checks equality of Strings that ignore order? For given example org.junit.Assert.assertEquals throws AssertionError
java.lang.AssertionError: expected:<[String A, String B]> but was:<[String B, String A]>
Work around is to sort Lists firstly and then pass them to assertion. But I want my code to be as simple and clean as possible.
I use Hamcrest 1.3, JUnit 4.11, Mockito 1.9.5.
回答1:
As you mention that you use Hamcrest, I would pick one of the collection Matchers
import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
import static org.junit.Assert.assertThat;
public class CompareListTest {
@Test
public void compareList() {
List<String> expected = Arrays.asList("String A", "String B");
List<String> actual = Arrays.asList("String B", "String A");
assertThat("List equality without order",
actual, containsInAnyOrder(expected.toArray()));
}
}
回答2:
You can use List.containsAll to check that the first list contains every element from the second one, and vice versa.
assertTrue(first.size() == second.size() &&
first.containsAll(second) && second.containsAll(first));
回答3:
Here's a solution that avoids quadratic complexity (iterating over the lists multiple times). This uses the Apache Commons CollectionUtils class to create a Map of each item to a frequency count itself in the list. It then simply compares the two Maps.
Assert.assertEquals("Verify same metrics series",
CollectionUtils.getCardinalityMap(expectedSeriesList),
CollectionUtils.getCardinalityMap(actualSeriesList));
I also just spotted CollectionUtils.isEqualCollection that claims to do exactly what is being requested here...
https://commons.apache.org/proper/commons-collections/apidocs/index.html?org/apache/commons/collections4/CollectionUtils.html
回答4:
Note that solution by Roberto Izquierdo has quadratic complexity in general. Solution on HashSets always has linear complexity:
assertTrue(first.size() == second.size() &&
new HashSet(first).equals(new HashSet(second)));
回答5:
You can use ListAssert that comes in junt-addons jar.
ListAssert.assertEquals(yourList, Arrays.asList(3, 4, 5));
回答6:
For a quick fix I would check both ways:
assertTrue(first.containsAll(second));
assertTrue(second.containsAll(first));
And trying with a situation where the number of the same elements is different (e.g. 1, 1, 2 and 1, 2, 2) I didn't get false positives.
回答7:
Im late to the party but here's my solution using Junit only. Any thoughts are welcome.
List<String> actual = new ArrayList<>();
actual.add("A");
actual.add("A");
actual.add("B");
List<String> expected = new ArrayList<>();
actual.add("A");
actual.add("B");
actual.add("B");
//Step 1: assert for size
assertEquals(actual.size(), expected.size());
//Step 2: Iterate
for(String e: expected){
assertTrue(actual.contains(e));
actual.remove(e);
}