web-dev-qa-db-fra.com

AssertEquals 2 Lists ignore order

Cela devrait être une question très simple, je crois. Mais de toute façon, je ne trouve pas de réponse dans Google.

Supposons que j'ai 2 listes de chaînes. Le premier contient "Chaîne A" et "Chaîne B" , le second contient "Chaîne B" et "Chaîne A" (remarquez la différence dans l'ordre). Je veux les tester avec JUnit pour vérifier s'ils contiennent exactement les mêmes Strings.

Existe-t-il une affirmation qui vérifie l’égalité des chaînes qui ignorent l’ordre? Par exemple, org.junit.Assert.assertEquals lève AssertionError. 

Java.lang.AssertionError: expected:<[String A, String B]> but was:<[String B, String A]>

La solution consiste à trier les listes d’abord, puis à les transmettre à une assertion. Mais je veux que mon code soit aussi simple et propre que possible.

J'utilise Hamcrest 1.3 , JUnit 4.11 , Mockito 1.9.5 .

54
kukis

Comme vous mentionnez que vous utilisez Hamcrest, je choisirais un des collectionneurs

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()));
    }

}
54
cheffe

Vous pouvez utiliser List.containsAll avec l'assertTrue de JUnit pour vérifier que la première liste contient tous les éléments du deuxième et vice versa.

assertTrue(first.size() == second.size() && 
    first.containsAll(second) && second.containsAll(first));
45
robertoia

Voici une solution qui évite la complexité quadratique (en parcourant les listes plusieurs fois). Ceci utilise la classe Apache Commons CollectionUtils pour créer une carte de chaque élément avec un compte de fréquence lui-même dans la liste. Il compare ensuite simplement les deux cartes. 

Assert.assertEquals("Verify same metrics series",
    CollectionUtils.getCardinalityMap(expectedSeriesList),
    CollectionUtils.getCardinalityMap(actualSeriesList));

Je viens également de repérer CollectionUtils.isEqualCollection qui prétend faire exactement ce qui est demandé ici ...

https://commons.Apache.org/proper/commons-collections/apidocs/index.html?org/Apache/commons/collections4/CollectionUtils.html

7
Alex Worden

Notez que la solution de Roberto Izquierdo a une complexité quadratique en général. La solution sur HashSets a toujours une complexité linéaire:

assertTrue(first.size() == second.size() &&
        new HashSet(first).equals(new HashSet(second)));
1
leventov

Vous pouvez utiliser ListAssert qui vient dans le jar de junt-addons.

ListAssert.assertEquals(yourList, Arrays.asList(3, 4, 5));
1
Akash
    Collections.sort(excepted);
    Collections.sort(actual);
    assertEquals(excepted,actual);
1
Tinyfool

Je suis en retard pour la fête, mais voici ma solution utilisant uniquement Junit. Toutes les pensées sont les bienvenues. 

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);
}
0
Sujit Joshi

Pour une solution rapide, je vérifierais dans les deux sens:

assertTrue(first.containsAll(second));
assertTrue(second.containsAll(first));

Et en essayant avec une situation où le nombre des mêmes éléments est différent (par exemple 1, 1, 2 et 1, 2, 2), je n’ai pas obtenu de faux positifs.

0

Avec AssertJ, containsExactlyInAnyOrder() ou containsExactlyInAnyOrderElementsOf() est ce dont vous avez besoin:

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

import Java.util.Arrays;
import Java.util.List;

public class CompareListTest {

    @Test
    public void compareListWithTwoVariables() {
        List<String> expected = Arrays.asList("String A", "String B");
        List<String> actual = Arrays.asList("String B", "String A");
        Assertions.assertThat(actual)
                  .containsExactlyInAnyOrderElementsOf(expected);
    }

    @Test
    public void compareListWithInlineExpectedValues() {
        List<String> actual = Arrays.asList("String B", "String A");
        Assertions.assertThat(actual)
                  .containsExactlyInAnyOrder("String A", "String B");
    }    
}
0
davidxxx