it-swarm.com.de

Bestätigen Sie eine Liste in Junit

Wie mache ich Assertions über eine Liste in einemJUnitTestfall? Nicht nur die Größe der Liste, sondern auch der Inhalt der Liste.

127
Kamal

Ich weiß, dass das vor ein paar Jahren gefragt wurde, wahrscheinlich war diese Funktion damals nicht verfügbar. Aber jetzt ist es einfach, dies einfach zu tun:

@Test
public void test_array_pass()
{
  List<String> actual = Arrays.asList("fee", "fi", "foe");
  List<String> expected = Arrays.asList("fee", "fi", "foe");

  assertThat(actual, is(expected));
  assertThat(actual, is(not(expected)));
}

Wenn Sie eine aktuelle Version von Junit mit hamcrest installiert haben, fügen Sie einfach diese Importe hinzu:

import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;

http://junit.org/junit4/javadoc/latest/org/junit/Assert.html#assertThat(T, org.hamcrest.Matcher)

http://junit.org/junit4/javadoc/latest/org/hamcrest/CoreMatchers.html

http://junit.org/junit4/javadoc/latest/org/hamcrest/core/Is.html

135
djeikyb

Dies ist eine ältere Antwort, die für JUnit 4.3 und darunter geeignet ist. Die moderne Version von JUnit enthält integrierte, lesbare Fehlermeldungen in der assertThat-Methode. Bevorzugen Sie andere Antworten zu dieser Frage, wenn möglich.

List<E> a = resultFromTest();
List<E> expected = Arrays.asList(new E(), new E(), ...);
assertTrue("Expected 'a' and 'expected' to be equal."+
            "\n  'a'        = "+a+
            "\n  'expected' = "+expected, 
            expected.equals(a));

Wie @Paul in seinem Kommentar zu dieser Antwort erwähnt, sind zwei Lists gleich:

if und nur wenn das angegebene Objekt auch eine Liste ist, haben beide Listen die gleiche Größe und alle entsprechenden Elementpaare in den beiden Listen sind gleich. (Zwei Elemente e1 und e2 sind gleich, wenn (e1==null ? e2==null : e1.equals(e2)).) Zwei Listen sind also gleich, wenn sie dieselben Elemente in derselben Reihenfolge enthalten. Diese Definition stellt sicher, dass die equals-Methode für verschiedene Implementierungen der List-Schnittstelle ordnungsgemäß funktioniert.

Siehe die JavaDocs der List-Schnittstelle .

19
Bart Kiers

Verwandle dich nicht in Zeichenfolge und vergleiche. Das ist nicht gut für die Leistung. Im Juni gibt es in Corematchers einen Matcher für diese => hasItems

List<Integer> yourList = Arrays.asList(1,2,3,4)    
assertThat(yourList, CoreMatchers.hasItems(1,2,3,4,5));

Dies ist der bessere Weg, den ich kenne, um Elemente in einer Liste zu überprüfen.

18
Andre Fonseca

Wenn Sie sich nicht für die Reihenfolge der Elemente interessieren, empfehle ich ListAssert.assertEquals in junit-addons.

Link: http://junit-addons.sourceforge.net/

Für faule Maven-Benutzer:

    <dependency>
        <groupId>junit-addons</groupId>
        <artifactId>junit-addons</artifactId>
        <version>1.4</version>
        <scope>test</scope>
    </dependency>
7
Viktor Nordling

assertEquals(Object, Object) aus JUnit4/JUnit 5 oder assertThat(actual, is(expected)); aus Hamcrest, die in den anderen Antworten vorgeschlagen werden, funktionieren nur, da sowohl equals() als auch toString() für die Klassen (und tief) der verglichenen Objekte überschrieben werden. 

Dies ist wichtig, weil der Gleichheitstest in der Assertion auf equals() basiert und die Testfehlermeldung auf toString() der verglichenen Objekte basiert.
Für integrierte Klassen wie String, Integer und so für ... kein Problem, da diese sowohl equals() als auch toString() überschreiben. Es ist also absolut gültig, List<String> oder List<Integer> mit assertEquals(Object,Object) zu bestätigen.
.__ Und zu diesem Thema: Sie müssen equals() in einer Klasse überschreiben, da dies in Bezug auf die Objektgleichheit sinnvoll ist, um Assertions nicht nur in einem Test mit JUnit einfacher zu machen.
Um Assertionen zu erleichtern, haben Sie andere Möglichkeiten.
Als eine gute Praxis bevorzuge ich Assertion/Matcher-Bibliotheken. 

Hier ist eine AssertJ -Lösung. 

org.assertj.core.api.ListAssert.containsExactly() ist das, was Sie brauchen: Es prüft, ob die tatsächliche Gruppe genau die angegebenen Werte enthält und nichts anderes, wie im Javadoc angegeben. 

Angenommen, eine Foo-Klasse, in der Sie Elemente hinzufügen und wo Sie diese erhalten können.
Ein Unit-Test von Foo, der behauptet, dass die beiden Listen den gleichen Inhalt haben, könnte folgendermaßen aussehen:

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

@Test
void add() throws Exception { 
   Foo foo = new Foo();
   foo.add("One", "Two", "Three");
   Assertions.assertThat(foo.getElements())
             .containsExactly("One", "Two", "Three");
}

Ein positiver AssertJ-Punkt ist, dass es unnötig ist, eine List wie erwartet zu deklarieren: Die Assertion wird gerader und der Code lesbarer:

Assertions.assertThat(foo.getElements())
         .containsExactly("One", "Two", "Three");

Assertion/Matcher-Bibliotheken sind jedoch ein Muss, da diese wirklich weiter gehen.
Nehmen wir an, dass Foo keine Strings, sondern Bars-Instanzen speichert.
Das ist ein sehr verbreitetes Bedürfnis. Mit AssertJ ist die Behauptung noch einfach zu schreiben. Besser können Sie behaupten, dass der Listeninhalt gleich ist, auch wenn die Klasse der Elemente equals()/hashCode() nicht überschreibt, während JUnit übrigens Folgendes erfordert:

import org.assertj.core.api.Assertions;
import static org.assertj.core.groups.Tuple.tuple;
import org.junit.jupiter.api.Test;

@Test
void add() throws Exception {
    Foo foo = new Foo();
    foo.add(new Bar(1, "One"), new Bar(2, "Two"), new Bar(3, "Three"));
    Assertions.assertThat(foo.getElements())
              .extracting(Bar::getId, Bar::getName)
              .containsExactly(Tuple(1, "One"),
                               Tuple(2, "Two"),
                               Tuple(3, "Three"));
}
4
davidxxx

wenn Sie keine Array-Liste erstellen möchten, können Sie dies auch versuchen 

@Test
public void test_array_pass()
{
  List<String> list = Arrays.asList("fee", "fi", "foe");
  Strint listToString = list.toString();
  Assert.assertTrue(listToString.contains("[fee, fi, foe]"));   // passes  
}
3
List<Integer> figureTypes = new ArrayList<Integer>(
                           Arrays.asList(
                                 1,
                                 2
                            ));

List<Integer> figureTypes2 = new ArrayList<Integer>(
                           Arrays.asList(
                                 1,
                                 2));

assertTrue(figureTypes .equals(figureTypes2 ));
3

Sie können assertEquals in junit verwenden. 

import org.junit.Assert;   
import org.junit.Test;

    @Test
    public void test_array_pass()
    {
        List<String> actual = Arrays.asList("fee", "fi", "foe");
        List<String> expected = Arrays.asList("fee", "fi", "foe");
        Assert.assertEquals(actual,expected);
    }

Wenn die Reihenfolge der Elemente unterschiedlich ist, wird ein Fehler ausgegeben.

Wenn Sie eine Modellobjektliste geltend machen, sollten Sie Überschreiben Sie die Equals-Methode im jeweiligen Modell.

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (obj != null && obj instanceof ModelName) {
            ModelName other = (ModelName) obj;
            return this.getItem().equals(other.getItem()) ;
        }
        return false;
    }
2
Dhyan Mohandas

Das Rad nicht neu erfinden!

Es gibt eine Google Code-Bibliothek, die dies für Sie erledigt: Hamcrest

[Hamcrest] Stellt eine Bibliothek mit Matcher-Objekten (auch als Einschränkungen oder Prädikate bezeichnet) bereit, mit der 'Match'-Regeln deklarativ definiert und in anderen Frameworks verwendet werden können. Typische Szenarien umfassen das Testen von Frameworks, Mocking-Bibliotheken und UI-Validierungsregeln.

1
Bohemian

Ich glaube nicht, dass die obigen Antworten genau die Lösung für den Vergleich von zwei Objektlisten bieten. Die meisten der oben genannten Ansätze können nur für die folgenden Grenzwerte der Vergleiche hilfreich sein. - Größenvergleich. Referenzvergleich

Wenn jedoch Objektlisten gleicher Größe und unterschiedliche Daten auf Objektebene vorhanden sind, helfen diese Vergleichsansätze nicht. 

Ich denke, der folgende Ansatz wird perfekt funktionieren, wenn die Gleichheits-Methode und die Hashcode-Methode für das benutzerdefinierte Objekt überschrieben werden.

Ich habe Xstream lib für "override" und "hashcode" verwendet, aber wir können "equals" und "hashcode" auch durch die gewonnene Logik/den Vergleich überschreiben.

Hier ist das Beispiel für Ihre Referenz

    import com.thoughtworks.xstream.XStream;

    import Java.text.ParseException;
    import Java.util.ArrayList;
    import Java.util.List;

    class TestClass {
      private String name;
      private String id;

      public void setName(String value) {
        this.name = value;
      }

      public String getName() {
        return this.name;
      }

      public String getId() {
        return id;
      }

      public void setId(String id) {
        this.id = id;
      }

      /**
       * @see Java.lang.Object#equals(Java.lang.Object)
       */
      @Override
      public boolean equals(Object o) {
        XStream xstream = new XStream();
        String oxml = xstream.toXML(o);
        String myxml = xstream.toXML(this);

        return myxml.equals(oxml);
      }

      /**
       * @see Java.lang.Object#hashCode()
       */
      @Override
      public int hashCode() {
        XStream xstream = new XStream();
        String myxml = xstream.toXML(this);
        return myxml.hashCode();
      }
    }

    public class XstreamCompareTest {
      public static void main(String[] args) throws ParseException {
      checkObjectEquals();
}

      private static void checkObjectEquals() {
        List<TestClass> testList1 = new ArrayList<TestClass>();
        TestClass tObj1 = new TestClass();
        tObj1.setId("test3");
        tObj1.setName("testname3");
        testList1.add(tObj1);

        TestClass tObj2 = new TestClass();
        tObj2.setId("test2");
        tObj2.setName("testname2");
        testList1.add(tObj2);

        testList1.sort((TestClass t1, TestClass t2) -> t1.getId().compareTo(t2.getId()));

        List<TestClass> testList2 = new ArrayList<TestClass>();
        TestClass tObj3 = new TestClass();
        tObj3.setId("test3");
        tObj3.setName("testname3");
        testList2.add(tObj3);

        TestClass tObj4 = new TestClass();
        tObj4.setId("test2");
        tObj4.setName("testname2");
        testList2.add(tObj4);

        testList2.sort((TestClass t1, TestClass t2) -> t1.getId().compareTo(t2.getId()));

        if (isNotMatch(testList1, testList2)) {
          System.out.println("The list are not matched");
        } else {
          System.out.println("The list are matched");
        }

      }

      private static boolean isNotMatch(List<TestClass> clist1, List<TestClass> clist2) {
        return clist1.size() != clist2.size() || !clist1.equals(clist2);
      }
    }

Das Wichtigste ist, dass Sie die Felder mit Annotation (@XStreamOmitField) ignorieren können, wenn Sie keine Felder in die Gleichheitsüberprüfung von Objekten einschließen möchten. Es gibt viele Anmerkungen wie diese, die konfiguriert werden müssen. Schauen Sie sich die Anmerkungen zu dieser Bibliothek an.

Ich bin mir sicher, dass diese Antwort Ihre Zeit erspart, um den richtigen Ansatz für den Vergleich zweier Objektlisten zu finden :) Bitte kommentieren Sie, wenn Sie diesbezüglich Probleme haben.

0