Hamcrest Custom Matchers

1. Inleiding

Evenals ingebouwde matchers, Hamcrest biedt ook ondersteuning voor het maken van aangepaste matchers.

In deze zelfstudie bekijken we hoe u ze kunt maken en gebruiken. Raadpleeg dit artikel om een ​​voorproefje te krijgen van de beschikbare matchers.

2. Aangepaste Matchers instellen

Om Hamcrest te krijgen, moeten we voeg de volgende Maven-afhankelijkheid toe aan onze pom.xml:

 org.hamcrest java-hamcrest 2.0.0.0 test 

De nieuwste Hamcrest-versie is te vinden op Maven Central.

3. Introductie Typ SafeMatcher

Voordat u met onze voorbeelden begint, het is belangrijk om de klas te begrijpen Typ SafeMatcher.We zullen deze klasse moeten uitbreiden om zelf een matcher te creëren.

Typ SafeMatcher is een abstracte klasse, dus alle subklassen moeten de volgende methoden implementeren:

  • wedstrijdenSafely (T t): bevat onze bijpassende logica
  • descriptionTo (Beschrijving beschrijving): past het bericht aan dat de klant krijgt als onze matching-logica niet wordt vervuld

Zoals we bij de eerste methode kunnen zien, Typ SafeMatcher is geparametriseerd, dus we zullen een type moeten declareren wanneer we het gebruiken. Dat is het type object dat we testen.

Laten we dit duidelijker maken door naar ons eerste voorbeeld in de volgende sectie te kijken.

4. Het creëren van het onlyDigits Matcher

Voor onze eerste use case, we maken een matcher die true retourneert als een bepaalde Draad bevat alleen cijfers.

Zo, onlyDigits toegepast op "123" zou moeten terugkeren waar terwijl "hallo1"En"doei”Moet false retourneren.

Laten we beginnen!

4.1. Matcher Creatie

Om te beginnen met onze matcher, maken we een klasse die zich uitbreidt Typ SafeMatcher:

public class IsOnlyDigits breidt TypeSafeMatcher uit {@Override beschermde boolean matchesSafely (String s) {// ...} @Override public void descriptTo (Description description) {// ...}}

Houd er rekening mee dat het object dat we testen een tekst is, we parametriseren onze subklasse van Typ SafeMatcher met de klas Draad.

Nu zijn we klaar om onze implementatie toe te voegen:

openbare klasse IsOnlyDigits breidt TypeSafeMatcher uit {@Override beschermde booleaanse matchesSafely (String s) {probeer {Integer.parseInt (s); terugkeer waar; } catch (NumberFormatException nfe) {return false; }} @Override public void descriptionTo (Beschrijving beschrijving) {description.appendText ("alleen cijfers"); }}

Zoals we kunnen zien, wedstrijdenSafey probeert onze input te ontleden Draad in een Geheel getal. Als het lukt, keert het terug waar. Als het niet lukt, keert het terug false. Het reageert met succes op onze use case.

Aan de andere kant, beschrijven naar voegt een tekst toe die onze verwachtingen weergeeft. We zullen zien hoe dit hierna wordt weergegeven wanneer we onze matcher gebruiken.

We hebben nog maar één ding nodig om onze matcher te voltooien: een statische methode om er toegang toe te krijgen, dus het gedraagt ​​zich als de rest van de ingebouwde matchers.

Dus we zullen zoiets als dit toevoegen:

openbare statische Matcher onlyDigits () {retourneer nieuwe IsOnlyDigits (); }

En we zijn klaar! Laten we in de volgende sectie kijken hoe we deze matcher kunnen gebruiken.

4.2. Matcher-gebruik

Naar gebruik onze gloednieuwe matcher, we maken een test:

@Test openbare ongeldig gegevenAString_whenIsOnlyDigits_thenCorrect () {String digits = "1234"; assertThat (cijfers, onlyDigits ()); }

En dat is het. Deze test zal slagen omdat de input Draad bevat alleen cijfers. Onthoud dat, om het wat beter leesbaar te maken, we kunnen de matcher gebruiken is dat fungeert als een wrapper over elke andere matcher:

assertThat (cijfers, is (onlyDigits ()));

Als we ten slotte dezelfde test zouden uitvoeren maar met de invoer "123ABC", zou het uitvoerbericht zijn:

java.lang.AssertionError: Verwacht: alleen cijfers maar: was "123ABC"

Hier zien we de tekst die we aan de beschrijven naar methode. Zoals we misschien hebben gemerkt, het is belangrijk om een ​​goede beschrijving te maken van wat er tijdens de test wordt verwacht.

5. deelbaar door

Dus, wat als we een matcher willen maken die bepaalt of een getal deelbaar is door een ander getal? Voor dat scenario we zullen een van de parameters ergens moeten opslaan.

Laten we eens kijken hoe we dat kunnen doen:

openbare klasse IsDivisibleBy breidt TypeSafeMatcher {private Integer divider uit; // constructors @Override beschermde booleaanse matchesSafely (integer dividend) {if (divider == 0) {return false; } rendement ((dividend% divider) == 0); } @Override public void descriptionTo (Beschrijving beschrijving) {description.appendText ("deelbaar door" + scheidingslijn); } openbare statische Matcher divisibleBy (Integer divider) {return new IsDivisibleBy (divider); }}

Simpel genoeg, we hebben zojuist een nieuw attribuut aan onze klas toegevoegd en het tijdens de constructie toegewezen. Vervolgens hebben we het gewoon als parameter doorgegeven aan onze statische methode:

@Test openbare leegte gegevenAnEvenInteger_whenDivisibleByTwo_thenCorrect () {Integer tien = 10; Geheel getal twee = 2; assertThat (tien, is (deelbaar door (twee))); } @Test openbare leegte gegevenAnOddInteger_whenNotDivisibleByTwo_thenCorrect () {Geheel getal elf = 11; Geheel getal twee = 2; assertThat (elf, is (not (deelbaar door (twee)))); }

En dat is het! We hebben onze matcher al met meer dan één input!

6. Conclusie

Hamcrest biedt matchers die de meeste gebruiksscenario's dekken waarmee een ontwikkelaar gewoonlijk te maken heeft bij het maken van beweringen.

Wat meer is, als een specifiek geval niet wordt gedekt, Hamcrest biedt ook ondersteuning om aangepaste matchers te maken die in specifieke scenario's kunnen worden gebruikt - zoals we hier hebben onderzocht. Ze zijn eenvoudig te maken en worden op precies dezelfde manier gebruikt als die in de bibliotheek.

Raadpleeg het GitHub-project om de volledige implementatie van deze voorbeelden te krijgen.