Benutzerdefinierte Assertions mit AssertJ

Benutzerdefinierte Zusicherungen mit AssertJ

 

1. Überblick

In diesem Tutorial werden wir die benutzerdefiniertenAssertJ-Assicherungen erstellen. die Grundlagen des AssertJcan be found here.

Mit benutzerdefinierten Zusicherungen können einfach nur Zusicherungen für unsere eigenen Klassen erstellt werden, sodass unsere Tests das Domänenmodell besser widerspiegeln.

2. Klasse im Test

Testfälle in diesem Tutorial basieren auf der KlassePerson:

public class Person {
    private String fullName;
    private int age;
    private List nicknames;

    public Person(String fullName, int age) {
        this.fullName = fullName;
        this.age = age;
        this.nicknames = new ArrayList<>();
    }

    public void addNickname(String nickname) {
        nicknames.add(nickname);
    }

    // getters
}

3. Benutzerdefinierte Assertionsklasse

Das Schreiben einer benutzerdefinierten AssertJ-Assertionsklasse ist ziemlich einfach. All we need to do is to declare a class that extends AbstractAssert, add a required constructor, and provide custom assertion methods.

Die Assertion-Klasse muss dieAbstractAssert-Klasse erweitern, um Zugriff auf wichtige Assertion-Methoden der API zu erhalten, z. B.isNotNull undisEqualTo.

Hier ist das Grundgerüst einer benutzerdefinierten Assertionsklasse fürPerson:

public class PersonAssert extends AbstractAssert {

    public PersonAssert(Person actual) {
        super(actual, PersonAssert.class);
    }

    // assertion methods described later
}

Bei der Erweiterung der KlasseAbstractAssertmüssen zwei Typargumente angegeben werden: Das erste ist die benutzerdefinierte Assertionsklasse selbst, die für die Methodenverkettung erforderlich ist, und das zweite ist die zu testende Klasse.

Um einen Einstiegspunkt für unsere Assertion-Klasse bereitzustellen, können wir eine statische Methode definieren, mit der eine Assertion-Kette gestartet werden kann:

public static PersonAssert assertThat(Person actual) {
    return new PersonAssert(actual);
}

Als Nächstes gehen wir einige benutzerdefinierte Zusicherungen durch, die in der KlassePersonAssertenthalten sind.

Die erste Methode überprüft, ob der vollständige Name einesPerson mit einemString-Argument übereinstimmt:

public PersonAssert hasFullName(String fullName) {
    isNotNull();
    if (!actual.getFullName().equals(fullName)) {
        failWithMessage("Expected person to have full name %s but was %s",
          fullName, actual.getFullName());
    }
    return this;
}

Die folgende Methode testet, ob einPerson ein Erwachsener ist, basierend auf seinemage:

public PersonAssert isAdult() {
    isNotNull();
    if (actual.getAge() < 18) {
        failWithMessage("Expected person to be adult");
    }
    return this;
}

Die letzte Überprüfung auf das Vorhandensein vonnickname:

public PersonAssert hasNickName(String nickName) {
    isNotNull();
    if (!actual.getNickNames().contains(nickName)) {
        failWithMessage("Expected person to have nickname %s",
          nickName);
    }
    return this;
}

Wenn Sie mehr als eine benutzerdefinierte Assertionsklasse haben, können wir alleassertThat-Methoden in eine Klasse einschließen und für jede der Assertionsklassen eine statische Factory-Methode bereitstellen:

public class Assertions {
    public static PersonAssert assertThat(Person actual) {
        return new PersonAssert(actual);
    }

    // static factory methods of other assertion classes
}

Die oben gezeigte KlasseAssertionsist ein praktischer Einstiegspunkt für alle benutzerdefinierten Assertionsklassen.

Statische Methoden dieser Klasse haben den gleichen Namen und unterscheiden sich durch ihren Parametertyp.

4. In Aktion

Die folgenden Testfälle veranschaulichen die benutzerdefinierten Zusicherungsmethoden, die wir im vorherigen Abschnitt erstellt haben. Beachten Sie, dass die MethodeassertThataus unserer benutzerdefinierten KlasseAssertionsimportiert wird, nicht aus der AssertJ-Kern-API.

So kann diehasFullName-Methode verwendet werden:

@Test
public void whenPersonNameMatches_thenCorrect() {
    Person person = new Person("John Doe", 20);
    assertThat(person)
      .hasFullName("John Doe");
}

Dies ist ein negativer Testfall, der dieisAdult-Methode veranschaulicht:

@Test
public void whenPersonAgeLessThanEighteen_thenNotAdult() {
    Person person = new Person("Jane Roe", 16);

    // assertion fails
    assertThat(person).isAdult();
}

und ein weiterer Test, der diehasNickname-Methode demonstriert:

@Test
public void whenPersonDoesNotHaveAMatchingNickname_thenIncorrect() {
    Person person = new Person("John Doe", 20);
    person.addNickname("Nick");

    // assertion will fail
    assertThat(person)
      .hasNickname("John");
}

5. Assertions Generator

Das Schreiben von benutzerdefinierten Zusicherungsklassen, die dem Objektmodell entsprechen, ebnet den Weg für gut lesbare Testfälle.

However, if we have a lot of classes, it would be painful to manually create custom assertion classes for all of them. Hier kommt der AssertJ-Assertions-Generator ins Spiel.

Um den Assertionsgenerator mit Maven zu verwenden, müssen wir der Dateipom.xmlein Plugin hinzufügen:


    org.assertj
    assertj-assertions-generator-maven-plugin
    2.1.0
    
        
            com.example.testing.assertj.custom.Person
        
    

Die neueste Version derassertj-assertions-generator-maven-plugin finden Sie unterhere.

Dasclasses-Element im obigen Plugin markiert Klassen, für die wir Zusicherungen generieren möchten. Weitere Konfigurationen des Plugins finden Sie unterthis post.

The AssertJ assertions generator creates assertions for each public property of the target class. Der spezifische Name jeder Assertionsmethode hängt vom Typ des Felds oder der Eigenschaft ab. Eine vollständige Beschreibung des Assertionsgenerators finden Sie unterthis reference.

Führen Sie den folgenden Maven-Befehl im Projektbasisverzeichnis aus:

mvn assertj:generate-assertions

Wir sollten Assertionsklassen sehen, die im Ordnertarget/generated-test-sources/assertj-assertions. For example,generiert wurden. Die generierte Einstiegspunktklasse für die generierten Assertions sieht folgendermaßen aus:

// generated comments are stripped off for brevity

package com.example.testing.assertj.custom;

@javax.annotation.Generated(value="assertj-assertions-generator")
public class Assertions {

    @org.assertj.core.util.CheckReturnValue
    public static com.example.testing.assertj.custom.PersonAssert
      assertThat(com.example.testing.assertj.custom.Person actual) {
        return new com.example.testing.assertj.custom.PersonAssert(actual);
    }

    protected Assertions() {
        // empty
    }
}

Jetzt können wir die generierten Quelldateien in das Testverzeichnis kopieren und dann benutzerdefinierte Assertionsmethoden hinzufügen, um unsere Testanforderungen zu erfüllen.

Es ist wichtig zu beachten, dass der generierte Code nicht garantiert vollständig korrekt ist. Zu diesem Zeitpunkt ist der Generator noch kein fertiges Produkt und die Community arbeitet daran.

Daher sollten wir den Generator als unterstützendes Werkzeug verwenden, um unser Leben zu erleichtern, anstatt es für selbstverständlich zu halten.

6. Fazit

In diesem Tutorial haben wir gezeigt, wie Sie benutzerdefinierte Zusicherungen zum manuellen und automatischen Erstellen von lesbarem Testcode mit der AssertJ-Bibliothek erstellen.

Wenn nur eine kleine Anzahl von Klassen getestet wird, ist die manuelle Lösung ausreichend. Andernfalls sollte der Generator verwendet werden.

Und wie immer kann die Implementierung aller Beispiele und Codefragmenteover on GitHub gefunden werden.