Verwendung von Hamcrest Number Matchers

Verwenden von Hamcrest-Nummernvergleichern

1. Überblick

Hamcrest provides static matchers to help make unit test assertions simpler and more legible. Sie können beginnen, einige der verfügbaren Matcherhere zu erkunden.

In diesem Artikel werden wir uns eingehender mit den nummerbezogenen Matchern befassen.

2. Konfiguration

Um Hamcrest zu erhalten, müssen wir unserenpom.xml nur die folgende Maven-Abhängigkeit hinzufügen:


    org.hamcrest
    java-hamcrest
    2.0.0.0

Die neueste Hamcrest-Version finden Sie aufMaven Central.

3. Näherungs-Matcher

Die ersten Matcher, die wir uns ansehen werden, sind diejenigen, diecheck if some element is close to a value +/- an error sind.

Formeller:

value - error <= element <= value + error

Wenn der obige Vergleich zutrifft, besteht die Behauptung.

Lassen Sie es uns in Aktion sehen!

3.1. isClose mitDouble Werten

Nehmen wir an, wir haben eine Zahl in einer Doppelvariablen namensactual. gespeichert. Wir möchten testen, obactual nahe 1 +/- 0,5 liegt.

Das ist:

1 - 0.5 <= actual <= 1 + 0.5
    0.5 <= actual <= 1.5

Erstellen wir nun einen Komponententest mit dem Matcher vonisClose:

@Test
public void givenADouble_whenCloseTo_thenCorrect() {
    double actual = 1.3;
    double operand = 1;
    double error = 0.5;

    assertThat(actual, closeTo(operand, error));
}

Da 1,3 zwischen 0,5 und 1,5 liegt, besteht der Test. Ebenso können wir das negative Szenario testen:

@Test
public void givenADouble_whenNotCloseTo_thenCorrect() {
    double actual = 1.6;
    double operand = 1;
    double error = 0.5;

    assertThat(actual, not(closeTo(operand, error)));
}

Schauen wir uns nun eine ähnliche Situation mit einem anderen Variablentyp an.

3.2. isClose mitBigDecimal Werten

isClose is overloaded and can be used same as with double values, but with BigDecimal objects:

@Test
public void givenABigDecimal_whenCloseTo_thenCorrect() {
    BigDecimal actual = new BigDecimal("1.0003");
    BigDecimal operand = new BigDecimal("1");
    BigDecimal error = new BigDecimal("0.0005");

    assertThat(actual, is(closeTo(operand, error)));
}

@Test
public void givenABigDecimal_whenNotCloseTo_thenCorrect() {
    BigDecimal actual = new BigDecimal("1.0006");
    BigDecimal operand = new BigDecimal("1");
    BigDecimal error = new BigDecimal("0.0005");

    assertThat(actual, is(not(closeTo(operand, error))));
}

Bitte beachten Sie, dassthe is matcher only decorates other matchers without adding extra logic. Dies macht die gesamte Behauptung nur lesbarer.

Das war's auch schon für Proximity-Matcher. Als Nächstes werfen wir einen Blick auf die Auftragsvergleicher.

4. Matchers bestellen

Wie der Name schon sagt,these matchers help make assertions regarding the order.

Es gibt fünf von ihnen:

  • compareEqualTo

  • größer als

  • größer als oder gleich wie

  • weniger als

  • weniger als oder gleich

Sie sind ziemlich selbsterklärend, aber sehen wir uns einige Beispiele an.

4.1. Bestellen Sie Matcher mitInteger VGehältern

Das häufigste Szenario wäreusing these matchers with numbers.

Lassen Sie uns also einige Tests erstellen:

@Test
public void given5_whenComparesEqualTo5_thenCorrect() {
    Integer five = 5;

    assertThat(five, comparesEqualTo(five));
}

@Test
public void given5_whenNotComparesEqualTo7_thenCorrect() {
    Integer seven = 7;
    Integer five = 5;

    assertThat(five, not(comparesEqualTo(seven)));
}

@Test
public void given7_whenGreaterThan5_thenCorrect() {
    Integer seven = 7;
    Integer five = 5;

    assertThat(seven, is(greaterThan(five)));
}

@Test
public void given7_whenGreaterThanOrEqualTo5_thenCorrect() {
    Integer seven = 7;
    Integer five = 5;

    assertThat(seven, is(greaterThanOrEqualTo(five)));
}

@Test
public void given5_whenGreaterThanOrEqualTo5_thenCorrect() {
    Integer five = 5;

    assertThat(five, is(greaterThanOrEqualTo(five)));
}

@Test
public void given3_whenLessThan5_thenCorrect() {
   Integer three = 3;
   Integer five = 5;

   assertThat(three, is(lessThan(five)));
}

@Test
public void given3_whenLessThanOrEqualTo5_thenCorrect() {
   Integer three = 3;
   Integer five = 5;

   assertThat(three, is(lessThanOrEqualTo(five)));
}

@Test
public void given5_whenLessThanOrEqualTo5_thenCorrect() {
   Integer five = 5;

   assertThat(five, is(lessThanOrEqualTo(five)));
}

Sinnvoll, oder? Beachten Sie, wie einfach es ist, die Aussagen der Prädikate zu verstehen.

4.2. Bestellen Sie Matcher mitString Werten

Obwohl das Vergleichen von Zahlen durchaus sinnvoll ist, ist es oft nützlich, andere Arten von Elementen zu vergleichen. Deshalborder matchers can be applied to any class that implements the Comparable interface.

Sehen wir uns einige Beispiele mitStrings: an

@Test
public void givenBenjamin_whenGreaterThanAmanda_thenCorrect() {
    String amanda = "Amanda";
    String benjamin = "Benjamin";

    assertThat(benjamin, is(greaterThan(amanda)));
}

@Test
public void givenAmanda_whenLessThanBenajmin_thenCorrect() {
    String amanda = "Amanda";
    String benjamin = "Benjamin";

    assertThat(amanda, is(lessThan(benjamin)));
}

String implementiert die alphabetische Reihenfolge incompareTo Methode über dieComparable-Schnittstelle.

Es macht also Sinn, dass das Wort „Amanda“ vor dem Wort „Benjamin“ steht.

4.3. Bestellen Sie Matcher mitLocalDate Werten

Wie beiStrings können wir Daten vergleichen. Schauen wir uns dieselben Beispiele an, die wir oben erstellt haben, aberLocalDate Objekte verwenden:

@Test
public void givenToday_whenGreaterThanYesterday_thenCorrect() {
    LocalDate today = LocalDate.now();
    LocalDate yesterday = today.minusDays(1);

    assertThat(today, is(greaterThan(yesterday)));
}

@Test
public void givenToday_whenLessThanTomorrow_thenCorrect() {
    LocalDate today = LocalDate.now();
    LocalDate tomorrow = today.plusDays(1);

    assertThat(today, is(lessThan(tomorrow)));
}

Es ist sehr schön zu sehen, dass die AnweisungassertThat(today, is(lessThan(tomorrow))) dem regulären Englisch nahe kommt.

4.4. Bestellen Sie Matcher mit benutzerdefinierten Klassenes

Warum also nicht unsere eigene Klasse erstellen undComparable? implementieren? Auf diese Weisewe can leverage order matchers to be used with custom order rules.

Beginnen wir mit der Erstellung einerPerson-Bean:

public class Person {
    String name;
    int age;

    // standard constructor, getters and setters
}

Implementieren wir nunComparable:

public class Person implements Comparable {

    // ...

    @Override
    public int compareTo(Person o) {
        if (this.age == o.getAge()) return 0;
        if (this.age > o.getAge()) return 1;
        else return -1;
    }
}

Die Implementierung voncompareTovergleicht zwei Personen nach ihrem Alter. Lassen Sie uns nun einige neue Tests erstellen:

@Test
public void givenAmanda_whenOlderThanBenjamin_thenCorrect() {
    Person amanda = new Person("Amanda", 20);
    Person benjamin = new Person("Benjamin", 18);

    assertThat(amanda, is(greaterThan(benjamin)));
}

@Test
public void
givenBenjamin_whenYoungerThanAmanda_thenCorrect() {
    Person amanda = new Person("Amanda", 20);
    Person benjamin = new Person("Benjamin", 18);

    assertThat(benjamin, is(lessThan(amanda)));
}

Matcher arbeiten jetzt basierend auf unserercompareTo-Logik.

5. NaN Matcher

Hamcrest liefertone extra number matcher to define if a number is actually, not a number:

@Test
public void givenNaN_whenIsNotANumber_thenCorrect() {
    double zero = 0d;

    assertThat(zero / zero, is(notANumber()));
}

6. Schlussfolgerungen

Wie Sie sehen können,number matchers are very useful to simplify common assertions.

Darüber hinaus sind Hamcrest-Matcher im Allgemeinenself-explanatory and easy to read.

All dies und die Möglichkeit, Matcher mit einer benutzerdefinierten Vergleichslogik zu kombinieren, machen sie zu einem leistungsstarken Tool für die meisten Projekte.

Die vollständige Implementierung der Beispiele aus diesem Artikel finden Sie inover on GitHub.