assertTrue () / assertFalse (): Nur zum Bestätigen des zurückgegebenen booleschen Ergebnisses
assertTrue (Iterables.elementsEqual (argumentComponents, returnComponents));
Sie möchten Assert.assertTrue()
oder Assert.assertFalse()
als zu testende Methode einen boolean
Wert zurückgeben.
Da die Methode eine bestimmte Sache zurückgibt, z. B. eine List
, die einige erwartete Elemente enthalten sollte, wird Folgendes behauptet assertTrue()
: Assert.assertTrue(myActualList.containsAll(myExpectedList)
ist ein Anti-Muster.
Es macht das Schreiben der Behauptung einfach, aber wenn der Test fehlschlägt, macht es auch das Debuggen schwierig, da der Testläufer Ihnen nur Folgendes sagt:
erwartet true
aber aktuell istfalse
Assert.assertEquals(Object, Object)
in JUnit4 oder Assertions.assertIterableEquals(Iterable, Iterable)
in JUnit 5: Nur als beides verwenden equals()
und toString()
für die Klassen (und tief) der verglichenen Objekte überschrieben werden
Dies ist wichtig, da sich der Gleichheitstest in der Zusicherung equals()
auf toString()
die verglichenen Objekte und die Testfehlermeldung auf diese stützt .
Da String
überschreibt beide equals()
und toString()
, ist es vollkommen gültig, das List<String>
mit zu behaupten assertEquals(Object,Object)
. Und zu diesem Thema: Sie müssen equals()
in einer Klasse überschreiben, weil dies im Hinblick auf die Objektgleichheit sinnvoll ist, nicht nur, um Aussagen in einem Test mit JUnit zu vereinfachen.
Um die Behauptungen zu vereinfachen, haben Sie andere Möglichkeiten (die Sie in den nächsten Punkten der Antwort sehen können).
Ist Guave eine Möglichkeit, Unit-Test-Assertions durchzuführen / zu erstellen?
Ist Google Guava Iterables.elementsEqual () der beste Weg, um diese beiden Listen zu vergleichen, vorausgesetzt, ich habe die Bibliothek in meinem Erstellungspfad?
Nein ist es nicht. Guava ist keine Bibliothek zum Schreiben von Unit-Test-Assertions.
Sie brauchen es nicht, um die meisten (alles, was ich denke) Unit-Tests zu schreiben.
Was ist der kanonische Weg, um Listen für Unit-Tests zu vergleichen?
Als gute Praxis bevorzuge ich Assertion / Matcher-Bibliotheken.
Ich kann JUnit nicht dazu ermutigen, bestimmte Behauptungen aufzustellen, da dies wirklich zu wenige und eingeschränkte Funktionen bietet: Es führt nur eine Behauptung mit einer tiefen Gleichheit aus.
Manchmal möchten Sie eine beliebige Reihenfolge in den Elementen zulassen, manchmal möchten Sie zulassen, dass alle Elemente der erwarteten mit der tatsächlichen übereinstimmen, und so weiter für ...
Die Verwendung einer Unit-Test-Assertion / Matcher-Bibliothek wie Hamcrest oder AssertJ ist daher der richtige Weg.
Die eigentliche Antwort bietet eine Hamcrest-Lösung. Hier ist eine AssertJ- Lösung.
org.assertj.core.api.ListAssert.containsExactly()
ist das, was Sie brauchen: Es überprüft, ob die tatsächliche Gruppe genau die angegebenen Werte und nichts anderes enthält, in der angegebenen Reihenfolge:
Überprüft, ob die tatsächliche Gruppe genau die angegebenen Werte enthält und nichts anderes in der angegebenen Reihenfolge.
Ihr Test könnte folgendermaßen aussehen:
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
@Test
void ofComponent_AssertJ() throws Exception {
MyObject myObject = MyObject.ofComponents("One", "Two", "Three");
Assertions.assertThat(myObject.getComponents())
.containsExactly("One", "Two", "Three");
}
Ein guter Punkt von AssertJ ist, dass es List
unnötig ist, a wie erwartet zu deklarieren : Dadurch wird die Assertion gerader und der Code besser lesbar:
Assertions.assertThat(myObject.getComponents())
.containsExactly("One", "Two", "Three");
Und wenn der Test fehlschlägt:
Assertions.assertThat(myObject.getComponents())
.containsExactly("One", "Two");
Sie erhalten eine sehr klare Nachricht wie:
java.lang.AssertionError:
Erwarten:
<["Eins", "Zwei", "Drei"]>
genau (und in derselben Reihenfolge) enthalten:
<["Eins", "Zwei"]>
Einige Elemente wurden jedoch nicht erwartet:
<["Drei"]>
Assertion / Matcher-Bibliotheken sind ein Muss, da diese wirklich weiter gehen
Angenommen, MyObject
es werden keine s-Instanzen gespeichert, String
sondern Foo
s-Instanzen wie:
public class MyFooObject {
private List<Foo> values;
@SafeVarargs
public static MyFooObject ofComponents(Foo... values) {
}
public List<Foo> getComponents(){
return new ArrayList<>(values);
}
}
Das ist ein sehr häufiges Bedürfnis. Mit AssertJ ist die Behauptung immer noch einfach zu schreiben. Besser können Sie behaupten, dass der Listeninhalt gleich ist, auch wenn die Klasse der Elemente nicht überschrieben wird, equals()/hashCode()
während JUnit-Methoden Folgendes erfordern:
import org.assertj.core.api.Assertions;
import static org.assertj.core.groups.Tuple.tuple;
import org.junit.jupiter.api.Test;
@Test
void ofComponent() throws Exception {
MyFooObject myObject = MyFooObject.ofComponents(new Foo(1, "One"), new Foo(2, "Two"), new Foo(3, "Three"));
Assertions.assertThat(myObject.getComponents())
.extracting(Foo::getId, Foo::getName)
.containsExactly(tuple(1, "One"),
tuple(2, "Two"),
tuple(3, "Three"));
}