2010-02-22 10 views
70

Wie würden Sie die Gleichheit von collections Elementen, genauer gesagt Set in JUnit 4, kurz und bündig behaupten?JUnit 4 vergleichen Collections

+2

Kontrolle dieses SO Post http://stackoverflow.com/questions/1086691/collectionassert-in-junit –

+0

Versuchen Sie zu bestätigen, dass zwei Sets gleich sind (die gleichen Elemente enthalten) oder dass zwei Elemente des gleichen Sets gleich sind? –

+0

Ich muss sehen, dass die Elemente von zwei Sets gleich sind – Eqbal

Antwort

74

Sie können nur behaupten, dass die beiden Sätze sind einander gleich, was die Set equals() method aufruft.

public class SimpleTest { 

    private Set<String> setA; 
    private Set<String> setB; 

    @Before 
    public void setUp() { 
     setA = new HashSet<String>(); 
     setA.add("Testing..."); 
     setB = new HashSet<String>(); 
     setB.add("Testing..."); 
    } 

    @Test 
    public void testEqualSets() { 
     assertEquals(setA, setB); 
    } 
} 

Dieser Test wird bestanden, wenn die beiden Sets die gleiche Größe haben und die gleichen Elemente enthalten.

+2

Funktioniert auch für Map. –

+4

Dies zeigt keine sehr guten Ergebnisse im Bericht. Wenn Ihre toStrings klar definiert sind, ist es besser, aber immer noch nicht gut (Ein kleiner Unterschied kann mit einer Seite Text enden) –

+0

Uhm, wie kommt es, ich bekomme: java.lang.AssertionError: erwartet: java.util.Hashtable <{ Company = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Kategorie = AvrIfd, QuoteId = 4342740204922826921}> aber war: java.util.Hashtable <{Company = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Kategorie = AvrIfd, QuoteId = 4342740204922826921}> –

10

mit hamcrest:

assertThat(s1, is(s2)); 

mit einfachen assert:

assertEquals(s1, s2); 

NB: t die equals() -Methode des Beton Setklasse ist

+0

Ich bevorzuge diese Methode, da Hamcrest mit JUnit 4 kommt, so dass es dort keine Notwendigkeit für andere Bibliotheken gibt. – JRSofty

+1

Dies funktioniert möglicherweise nicht, wenn die Sets unterschiedliche Typen haben. –

2

prüfen this article verwendet. Ein Beispiel von dort:

@Test 
public void listEquality() { 
    List<Integer> expected = new ArrayList<Integer>(); 
    expected.add(5); 

    List<Integer> actual = new ArrayList<Integer>(); 
    actual.add(5); 

    assertEquals(expected, actual); 
} 
+0

kurz aber toll Link, erklärt wirklich schnell, was man mit Junit4- – Johannes

+0

machen kann Der Link ist kaputt. Gibt es eine Chance, eine archivierte Version online zu finden oder den Inhalt zusammenzufassen? – pzp

6

Ein besonders interessanter Fall ist, wenn man

java.util.Arrays$ArrayList<[[name,value,type], [name1,value1,type1]]> 

und

vergleichen
java.util.Collections$UnmodifiableCollection<[[name,value,type], [name1,value1,type1]]> 

Bisher war die einzige Lösung, die ich sehe, ist sie beide in Sätze

assertEquals(new HashSet<CustomAttribute>(customAttributes), new HashSet<CustomAttribute>(result.getCustomAttributes())); 

zu ändern Oder ich könnte sie Element für Element vergleichen.

+0

Tatsächlich gibt es mehrere Lösungen für das in den anderen Antworten dargestellt. Sätze sind ein wenig unglücklich dafür, da sie die Reihenfolge ignorieren. Vielleicht ArrayList? –

29

Apache commons zur Rettung wieder.

assertTrue(CollectionUtils.isEqualCollection(coll1, coll2)); 

Funktioniert wie ein Charme. Ich weiß nicht warum, aber ich habe festgestellt, dass bei Sammlungen die folgenden assertEquals(coll1, coll2) nicht immer funktioniert. In dem Fall, in dem es für mich fehlschlug, hatte ich zwei Sammlungen, die von Sets unterstützt wurden. Weder Hamcrest noch Junit würden sagen, dass die Sammlungen gleich waren, obwohl ich sicher wusste, dass sie es waren. Mit CollectionUtils funktioniert es perfekt.

+14

Das ist eigentlich trivial, der knifflige Teil ist es, den Unterschied zum Anrufer deutlich anzuzeigen –

+1

Die akzeptierte Antwort ist eine gute Antwort für die ursprüngliche Frage (Unit Test speziell für zwei Sets) aber diese Antwort mit CollectionUtils ist meiner Meinung nach eine bessere Antwort der allgemeinste Fall. Ich konnte eine Sammlung und ein Set nur mit Hilfe von CollectionUtils vergleichen. – Jay

4

Als zusätzliche Methode, die Array-basiert ist, können Sie ungeordnete Array-Assertions in Junitx verwenden. Obwohl das Beispiel Apache CollectionUtils funktioniert, gibt es ein thepacakge feste Behauptung Erweiterungen auch dort:

denke ich, dass der

ArrayAssert.assertEquivalenceArrays(new Integer[]{1,2,3}, new Integer[]{1,3,2}); 

Ansatz viel besser lesbar sein und debug für Sie (alle Sammlungen unterstützen toArray(), so sollte es einfach genug sein, die ArrayAssert-Methoden zu verwenden.

Natürlich ist der Nachteil hier, dass Junitx eine zusätzliche JAR-Datei oder Maven-Eintrag ist ...

<dependency org="junit-addons" name="junit-addons" rev="1.4"/> 
0

Wenn Sie, ob eine Liste überprüfen mögen oder Set enthält eine Reihe spezifischer Werte (statt es mit einer bereits bestehenden Sammlung zu vergleichen), oft die toString Methode der Sammlungen ist praktisch:

String[] actualResult = calltestedmethod(); 
assertEquals("[foo, bar]", Arrays.asList(actualResult).toString()); 

List otherResult = callothertestedmethod(); 
assertEquals("[42, mice]", otherResult.toString()); 

Dies ist ein bisschen kürzer als zuerst die erwartete Sammlung zu konstruieren und mit der tatsächlichen Sammlung zu vergleichen, und einfacher zu schreiben und zu korrigieren.

(Zugegeben, das ist keine besonders saubere Methode und kann kein Element "foo, bar" von zwei Elementen "foo" und "bar" unterscheiden. Aber in der Praxis denke ich, dass es am wichtigsten ist, dass es einfach ist schnelle Tests zu schreiben, sonst viele Entwickler einfach nicht ohne gedrückt)

+0

Dadurch hängt das Ergebnis des Komponententests von der Implementierung von toString aus der Liste ab. Wenn sie sich entscheiden, die Formatierung zu ändern, wird der Komponententest nicht mehr funktionieren. Ich würde das nicht für sicher halten. –

+0

@ LaurensOp'tZandt Sie meinen, dass Oracle das Format von Collection.toList() ändert? Das wird sicher nicht passieren. Sie haben jedoch Recht, das ist nicht besonders sauber. Aber in der Praxis habe ich den Eindruck, dass es sehr wichtig ist, Tests zu schreiben. –

+0

Ich stimme zu, ich denke, die ToString-Methode wird wahrscheinlich nicht wahrscheinlichen. Also wird es wahrscheinlich weiter funktionieren. Ich wollte nur darauf hinweisen, dass es nicht sehr sauber ist. Aber es ist wirklich sehr einfach. Ein Problem, das auftritt, ist, wenn Sätze verglichen werden. Da ist ihre Bestellung nicht garantiert. –

2

hamcrest verwenden.

assertThat(set1, both(everyItem(isIn(set2))).and(containsInAnyOrder(set1))); 

Dies funktioniert auch, wenn die Sätze unterschiedliche Datentypen haben, und Berichte über den Unterschied statt nur versagt .

+1

Was ist der Import für isIn? IntelliJ kann den Import mit keinem Hamcret-Paket auflösen. – fabien

0

Ich mag die Lösung von Hans-Peter Störr ... Aber ich denke, es ist nicht ganz richtig. Leider akzeptiert containsInAnyOrder keine Collection von Objekten, mit denen zu vergleichen ist. So hat es ein Collection von Matcher s sein:

assertThat(set1, containsInAnyOrder(set2.stream().map(IsEqual::equalTo).collect(toList()))) 

Der Import sind:

import static java.util.stream.Collectors.toList; 
import static org.hamcrest.Matchers.containsInAnyOrder; 
import static org.junit.Assert.assertThat;