JUnit 4 Vergleiche Sets


102

Wie würden Sie die Gleichheit der CollectionElemente, insbesondere a Setin JUnit 4, kurz und bündig behaupten ?



Versuchen Sie zu behaupten, dass zwei Mengen gleich sind (dieselben Elemente enthalten) oder dass zwei Elemente derselben Menge gleich sind?
Bill the Lizard

Ich muss sehen, dass die Elemente von zwei Mengen gleich sind
Gl.

Antworten:


103

Sie können behaupten, dass die beiden Sets gleich sind, wodurch die Set equals()Methode aufgerufen wird .

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

Dies @Testist erfolgreich, wenn die beiden Sets dieselbe Größe haben und dieselben Elemente enthalten.


7
Dies zeigt keine sehr guten Ergebnisse im Bericht an. Wenn Ihre toStrings klar definiert sind, ist es besser, aber immer noch nicht gut (Ein kleiner Unterschied kann zu einer Textseite führen)
Bill K

Ähm, wie kommt es, dass ich: java.lang.AssertionError: erwartet: java.util.Hashtable <{CompanyName = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Category = AvrIfd, QuoteId> = 8PKQ9va3nW8pRWb4SjPF2DvdQDBmlZ, Ric = sZwmXAdYKv, Kategorie = AvrIfd, QuoteId = 4342740204922826921}>
Giovanni Botta

3
@Giodude Haben Sie, equalsund hashCodein der Klasse implementiert , dass Sie in Ihrem Hashtable sind speichern?
Bill the Lizard

Wie Sie sehen können, sind dies nur Zeichenfolgen und eine lange ... Ich teste Avro, um eine Karte zu serialisieren und zu de-serialisieren, und das ist das Ergebnis. Ich denke, es muss etwas faul sein mit der Art und Weise, wie die Zeichenfolgen serialisiert und de-serialisiert werden, was den Test zum Scheitern bringt, aber ich kann das Problem nicht finden.
Giovanni Botta

Hat bei mir nicht funktioniert, obwohl ich zwei HashSet <Long> vergleiche. @ MattFriedman Antwort funktioniert tatsächlich für meinen Anwendungsfall.
Bluecollarcoder

46

Apache kommt wieder zur Rettung.

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

Klappt wunderbar. Ich weiß nicht warum, aber ich habe festgestellt, dass bei Sammlungen Folgendes assertEquals(coll1, coll2)nicht immer funktioniert. Für den Fall, dass 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.


20
Dies ist eigentlich trivial, der schwierige Teil ist es, den Unterschied zum Anrufer klar anzuzeigen
Bill K

1
Die akzeptierte Antwort ist eine gute Antwort auf die ursprüngliche Frage (Komponententest speziell für zwei Sätze), aber diese Antwort mit CollectionUtils ist meiner Meinung nach eine bessere Antwort für den allgemeinsten Fall. Ich konnte eine Sammlung und ein Set nur mit CollectionUtils vergleichen.
Jay

16

mit hamcrest :

assertThat(s1, is(s2));

mit klarer Behauptung:

assertEquals(s1, s2);

NB: t Die Methode equals () der konkreten Mengenklasse wird verwendet


1
Ich bevorzuge diese Methode, da Hamcrest mit JUnit 4 geliefert wird und daher keine weiteren Bibliotheken erforderlich sind.
JRSofty

2
Dies funktioniert möglicherweise nicht, wenn die Sets unterschiedliche Typen haben.
Hans-Peter Störr

7

Ein besonders interessanter Fall ist der Vergleich

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

und

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

Bisher sehe ich nur die Lösung, beide in Sets umzuwandeln

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

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


Tatsächlich gibt es dafür mehrere Lösungen, die in den anderen Antworten vorgestellt werden. Sets sind dafür sowieso etwas unglücklich, da sie die Reihenfolge ignorieren. Vielleicht ArrayList?
Hans-Peter Störr

4

Als zusätzliche Methode, die auf Arrays basiert, können Sie die Verwendung ungeordneter Array-Zusicherungen in junitx in Betracht ziehen. Obwohl das Beispiel Apache CollectionUtils funktioniert, gibt es dort auch eine Reihe solider Assertion-Erweiterungen:

ich glaube, dass der

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

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

Der Nachteil hierbei ist natürlich, dass junitx eine zusätzliche JAR-Datei oder ein Maven-Eintrag ist ...

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

2

Überprüfen Sie diesen Artikel . 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);  
}  

kurzer aber toller Link, erklärt sehr schnell, was man mit Junit4- machen kann
Johannes

1
Die Verbindung ist unterbrochen. Gibt es eine Chance, dass Sie eine archivierte Version online finden oder deren Inhalt zusammenfassen können?
pzp

1

Verwenden von Hamcrest:

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

Dies funktioniert auch, wenn die Sets unterschiedliche Datentypen haben und über den Unterschied berichten, anstatt nur zu versagen.


2
Was ist der Import für isIn? IntelliJ kann den Import mit keinem hamcret-Paket auflösen.
Fabien

0

Wenn Sie überprüfen möchten, ob eine Liste oder ein Satz einen Satz bestimmter Werte enthält (anstatt ihn mit einer bereits vorhandenen Sammlung zu vergleichen), ist häufig die toString-Methode für Sammlungen hilfreich:

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

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

Dies ist etwas kürzer als das erste Erstellen der erwarteten Sammlung und der Vergleich mit der tatsächlichen Sammlung und einfacher zu schreiben und zu korrigieren.

(Zugegeben, dies ist keine besonders saubere Methode und kann ein Element "foo, bar" nicht von zwei Elementen "foo" und "bar" unterscheiden. In der Praxis halte ich es jedoch für das Wichtigste, dass es einfach und schnell ist, Tests zu schreiben , sonst werden viele Entwickler einfach nicht ohne Druck.)


Dadurch hängt das Ergebnis Ihres Komponententests von der Implementierung von toString from list ab. Wenn sie die Formatierung ändern, funktioniert der Komponententest nicht mehr. Ich würde das nicht für sicher halten.
Laurens Op 't Zandt

@ LaurensOp'tZandt Du meinst, Oracle ändert das Format von Collection.toList ()? Das wird sicher nicht passieren. Sie haben jedoch Recht, das ist nicht besonders sauber. Aber in der Praxis ist mein Eindruck, dass es am wichtigsten ist, dass es sehr einfach ist, Tests zu schreiben.
Hans-Peter Störr

Ich stimme zu, ich denke, die toString-Methode wird wahrscheinlich kein Zufall sein. Also wird es wahrscheinlich weiter funktionieren. Ich wollte nur darauf hinweisen, dass es kein sehr sauberer Weg ist. Aber in der Tat ist es sehr einfach. Ein Problem, das auftritt, ist beim Vergleichen von Mengen. Da ihre Bestellung nicht garantiert ist.
Laurens Op 't Zandt

0

Ich mag die Lösung von Hans-Peter Störr ... Aber ich denke, es ist nicht ganz richtig. Leider containsInAnyOrdernicht Akzeptierte Collectionvon objetcs zu vergleichen. Also muss es ein Collectionvon Matchers sein:

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

Die Importe sind:

import static java.util.stream.Collectors.toList;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertThat;
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.