Test med Hamcrest

1. Oversigt

Hamcrest er den velkendte ramme, der bruges til enhedstest i Java-økosystemet. Det er samlet i JUnit og enkelt sagt bruger det eksisterende prædikater - kaldet matcherklasser - til at komme med påstande.

I denne vejledning vil vi udforsk Hamcrest API og lære at drage fordel af det til at skrive pænere og mere intuitive enhedstest til vores software.

2. Hamcrest-opsætning

Vi kan bruge Hamcrest med maven ved at tilføje følgende afhængighed til vores pom.xml fil:

 org.hamcrest hamcrest-all 1.3 

Den seneste version af dette bibliotek kan altid findes her.

3. Et eksempel på en test

Hamcrest bruges ofte med junit og andre testrammer til påstander. Specifikt i stedet for at bruge junit'S talrige hævde metoder, bruger vi kun API's single hævder det erklæring med passende matchere.

Lad os se på et eksempel, der tester to Snors for ligestilling uanset sag. Dette skulle give os en klar idé om, hvordan Hamcrest passer ind i en testmetode:

offentlig klasse StringMatcherTest {@Test offentlig ugyldighed given2Strings_whenEqual_thenCorrect () {String a = "foo"; Streng b = "FOO"; hævder, at (a, equalToIgnoringCase (b)); }}

I de følgende afsnit skal vi se på flere andre almindelige matchere Hamcrest tilbud.

4. Den Objekt Matcher

Hamcrest giver matchere til at foretage påstande om vilkårlige Java-objekter.

At hævde, at toString metode til en Objekt returnerer en specificeret Snor:

@Test offentlig ugyldighed givenBean_whenToStringReturnsRequiredString_thenCorrect () {Person person = ny person ("Barrack", "Washington"); Streng str = person.toString (); assertThat (person, hasToString (str)); }

Vi kan også kontrollere, at en klasse er en underklasse af en anden:

@Test offentlig ugyldighed givet2Classes_whenOneInheritsFromOther_thenCorrect () {assertThat (Cat.class, typeCompatibleWith (Animal.class)); }}

5. Bean Matcher

Vi kan bruge Hamcrest'S Bean matcher til inspektion af egenskaber for en Java bønne.

Antag følgende Person bønne:

offentlig klasse Person {String name; Strengadresse; offentlig person (String personName, String personAddress) {name = personName; adresse = personAdresse; }}

Vi kan kontrollere, om bønnen har ejendommen, navn ligesom:

@Test offentligt ugyldigt givenBean_whenHasValue_thenCorrect () {Person person = ny person ("Baeldung", 25); assertThat (person, hasProperty ("navn")); }

Vi kan også kontrollere, om Person har adresse ejendom, initialiseret til New York:

@Test offentligt ugyldigt givenBean_whenHasCorrectValue_thenCorrect () {Person person = ny person ("Baeldung", "New York"); assertThat (person, hasProperty ("adresse", equalTo ("New York"))); }

Vi kan lige så godt kontrollere, om to Person objekter er konstrueret med de samme værdier:

@ Test offentlig ugyldighed given2Beans_whenHavingSameValues_thenCorrect () {Person person1 = ny person ("Baeldung", "New York"); Person person2 = ny person ("Baeldung", "New York"); assertThat (person1, samePropertyValuesAs (person2)); } 

6. Den Kollektion Matcher

Hamcrest giver matchere til inspektion Kollektions.

Enkel kontrol for at finde ud af, om en Kollektion er tom:

@Test offentligt ugyldigt givenCollection_whenEmpty_thenCorrect () {List emptyList = new ArrayList (); assertThat (tomListe, tom ()); }

For at kontrollere størrelsen på en Kollektion:

@Test offentligt ugyldigt givetAList_whenChecksSize_thenCorrect () {Liste hamcrestMatchers = Arrays.asList ("samlinger", "bønner", "tekst", "nummer"); assertThat (hamcrestMatchers, hasSize (4)); }

Vi kan også bruge det til at hævde, at en matrix har den krævede størrelse:

@ Test offentligt ugyldigt givenArray_whenChecksSize_thenCorrect () {String [] hamcrestMatchers = {"samlinger", "bønner", "tekst", "nummer"}; assertThat (hamcrestMatchers, arrayWithSize (4)); }

For at kontrollere, om en Kollektion indeholder givne medlemmer, uanset rækkefølge:

@Test offentligt ugyldigt givetAListAndValues_whenChecksListForGivenValues_thenCorrect () {Liste hamcrestMatchers = Arrays.asList ("samlinger", "bønner", "tekst", "nummer"); assertThat (hamcrestMatchers, indeholderInAnyOrder ("bønner", "tekst", "samlinger", "nummer")); }

For yderligere at hævde, at Kollektion medlemmer er i rækkefølge:

@Test offentligt ugyldigt givetAListAndValues_whenChecksListForGivenValuesWithOrder_thenCorrect () {Liste hamcrestMatchers = Arrays.asList ("samlinger", "bønner", "tekst", "nummer"); assertThat (hamcrestMatchers, indeholder ("samlinger", "bønner", "tekst", "nummer")); }

Sådan kontrolleres, om en matrix har et enkelt givet element:

@Test offentlig ugyldighed givenArrayAndValue_whenValueFoundInArray_thenCorrect () {String [] hamcrestMatchers = {"samlinger", "bønner", "tekst", "nummer"}; assertThat (hamcrestMatchers, hasItemInArray ("tekst")); }

Vi kan også bruge en alternativ matcher til den samme test:

@Test offentlig ugyldighed givenValueAndArray_whenValueIsOneOfArrayElements_thenCorrect () {String [] hamcrestMatchers = {"samlinger", "bønner", "tekst", "nummer"}; assertThat ("tekst", isOneOf (hamcrestMatchers)); }

Eller stadig kan vi gøre det samme med en anden matcher som sådan:

@Test offentlig ugyldighed givenValueAndArray_whenValueFoundInArray_thenCorrect () {String [] array = new String [] {"collection", "beans", "text", "number"}; assertThat ("bønner", isIn (array)); }

Vi kan også kontrollere, om matrixen indeholder givne elementer uanset rækkefølge:

@Test offentlig ugyldighed givenArrayAndValues_whenValuesFoundInArray_thenCorrect () {String [] hamcrestMatchers = {"samlinger", "bønner", "tekst", "nummer"}; assertThat (hamcrestMatchers, arrayContainingInAnyOrder ("bønner", "samlinger", "nummer", "tekst")); }

For at kontrollere, om matrixen indeholder givne elementer, men i den givne rækkefølge:

@Test offentlig ugyldighed givenArrayAndValues_whenValuesFoundInArrayInOrder_thenCorrect () {String [] hamcrestMatchers = {"samlinger", "bønner", "tekst", "nummer"}; assertThat (hamcrestMatchers, arrayContaining ("samlinger", "bønner", "tekst", "nummer")); }

Når vores Kollektion er en Kort, vi kan bruge følgende matchere i disse respektive funktioner:

For at kontrollere, om den indeholder en given nøgle:

@Test offentlig ugyldighed givenMapAndKey_whenKeyFoundInMap_thenCorrect () {Map map = new HashMap (); map.put ("blogname", "baeldung"); assertThat (kort, hasKey ("blogname")); }

og en given værdi:

@Test offentlig ugyldighed givenMapAndValue_whenValueFoundInMap_thenCorrect () {Map map = new HashMap (); map.put ("blogname", "baeldung"); assertThat (map, hasValue ("baeldung")); }

og endelig en given post (nøgle, værdi):

@ Test offentligt ugyldigt givenMapAndEntry_whenEntryFoundInMap_thenCorrect () {Map map = new HashMap (); map.put ("blogname", "baeldung"); assertThat (kort, hasEntry ("blogname", "baeldung")); }

7. Den Nummer Matcher

Det Nummer matchere bruges til at udføre påstande om variabler af Nummer klasse.

At tjekke bedre end tilstand:

@Test offentlig ugyldighed givenAnInteger_whenGreaterThan0_thenCorrect () {assertThat (1, greaterThan (0)); }

At tjekke bedre end eller svarende til tilstand:

@Test offentligt ugyldigt givenAnInteger_whenGreaterThanOrEqTo5_thenCorrect () {assertThat (5, greaterThanOrEqualTo (5)); }

At tjekke Mindre end tilstand:

@Test offentlig ugyldighed givenAnInteger_whenLessThan0_thenCorrect () {assertThat (-1, lessThan (0)); }

At tjekke Mindre end eller svarende til tilstand:

@Test offentligt ugyldigt givenAnInteger_whenLessThanOrEqTo5_thenCorrect () {assertThat (-1, lessThanOrEqualTo (5)); }

At tjekke tæt på tilstand:

@Test offentligt ugyldigt givetADouble_whenCloseTo_thenCorrect () {assertThat (1.2, closeTo (1, 0.5)); }

Lad os være meget opmærksomme på den sidste matcher, tæt på. Det første argument, operanden, er det, som målet sammenlignes med, og det andet argument er den tilladte afvigelse fra operanden . Dette betyder, at hvis målet er operand + afvigelse eller operand-afvigelse, vil testen bestå.

8. Tekstmatcher

Påstand om Snors gøres nemmere, pænere og mere intuitivt med Hamcrest'S tekst matchere. Vi vil se på dem i dette afsnit.

For at kontrollere, om en Snor er tom:

@Test offentlig ugyldighed givenString_whenEmpty_thenCorrect () {String str = ""; assertThat (str, isEmptyString ()); }

For at kontrollere, om en Snor er tom eller nul:

@Test offentlig ugyldighed givenString_whenEmptyOrNull_thenCorrect () {String str = null; assertThat (str, isEmptyOrNullString ()); }

At kontrollere for lighed med to Snors mens du ignorerer det hvide rum:

@Test offentlig ugyldighed given2Strings_whenEqualRegardlessWhiteSpace_thenCorrect () {String str1 = "text"; String str2 = "tekst"; assertThat (str1, equalToIgnoringWhiteSpace (str2)); }

Vi kan også kontrollere, om der er en eller flere understrenge i en given Snor i en given rækkefølge:

@ Test offentligt ugyldigt givenString_whenContainsGivenSubstring_thenCorrect () {String str = "kalligrafi"; assertThat (str, stringContainsInOrder (Arrays.asList ("kald", "graf"))); }

Endelig kan vi kontrollere, om der er to Snors uanset sag:

@Test offentligt ugyldigt given2Strings_whenEqual_thenCorrect () {String a = "foo"; Streng b = "FOO"; hævder, at (a, equalToIgnoringCase (b)); }

9. Core API

Det Hamcrest core API skal bruges af tredjeparts rammeleverandører. Det giver os dog nogle gode konstruktioner til at gøre vores enhedstests mere læsbare og også nogle kernematchere, der kan bruges lige så let.

Læsbarhed med er konstruer på en matcher:

@Test offentlig ugyldighed given2Strings_whenIsEqualRegardlessWhiteSpace_thenCorrect () {String str1 = "text"; String str2 = "tekst"; assertThat (str1, er (equalToIgnoringWhiteSpace (str2))); }

Det er konstruer på en simpel datatype:

@Test offentligt ugyldigt given2Strings_whenIsEqual_thenCorrect () {String str1 = "text"; String str2 = "tekst"; hævder, at (str1, er (str2)); }

Negation med ikke konstruer på en matcher:

@Test offentlig ugyldighed given2Strings_whenIsNotEqualRegardlessWhiteSpace_thenCorrect () {String str1 = "text"; String str2 = "tekster"; assertThat (str1, ikke (equalToIgnoringWhiteSpace (str2))); }

Det ikke konstruer på en simpel datatype:

@Test offentligt ugyldigt given2Strings_whenNotEqual_thenCorrect () {String str1 = "text"; String str2 = "tekster"; hævder, at (str1, ikke (str2)); }

Kontroller, om en Snor indeholder en given understreng:

@Test offentligt ugyldigt givetAStrings_whenContainsAnotherGivenString_thenCorrect () {String str1 = "kalligrafi"; String str2 = "call"; assertThat (str1, indeholderString (str2)); }

Kontroller, om en Snor starter med en given understreng:

@Test offentlig ugyldighed givetAString_whenStartsWithAnotherGivenString_thenCorrect () {String str1 = "kalligrafi"; String str2 = "call"; assertThat (str1, startsWith (str2)); }

Kontroller, om en Snor ender med en given understreng:

@Test offentligt ugyldigt givetAString_whenEndsWithAnotherGivenString_thenCorrect () {String str1 = "kalligrafi"; Streng str2 = "phy"; assertThat (str1, endsWith (str2)); }

Kontroller, om der er to Objekts er af samme forekomst:

@Test offentligt ugyldigt given2Objects_whenSameInstance_thenCorrect () {Cat cat = new Cat (); assertThat (kat, sameInstance (kat)); }

Kontroller, om en Objekt er en forekomst af en given klasse:

@Test offentlig ugyldighed givenAnObject_whenInstanceOfGivenClass_thenCorrect () {Cat cat = new Cat (); assertThat (cat, instanceOf (Cat.class)); }

Kontroller, om alle medlemmer af en Kollektion opfylder en betingelse:

@ Test offentligt ugyldigt givenList_whenEachElementGreaterThan0_thenCorrect () {List list = Arrays.asList (1, 2, 3); int baseCase = 0; assertThat (liste, everyItem (greaterThan (baseCase))); }

Kontroller, at en Snor er ikke nul:

@Test offentlig ugyldighed givenString_whenNotNull_thenCorrect () {String str = "notnull"; assertThat (str, notNullValue ()); }

Kædeforhold sammen, test passerer når målet opfylder en af ​​betingelserne, svarende til logisk ELLER:

@Test offentlig ugyldighed givenString_whenMeetsAnyOfGivenConditions_thenCorrect () {String str = "kalligrafi"; String start = "call"; String end = "foo"; assertThat (str, anyOf (startsWith (start), indeholderString (end))); }

Kædeforhold sammen, testen går kun, når målet opfylder alle betingelser, svarende til logisk OG:

@Test offentlig ugyldighed givenString_whenMeetsAllOfGivenConditions_thenCorrect () {String str = "kalligrafi"; String start = "call"; String end = "phy"; assertThat (str, allOf (startsWith (start), endsWith (end))); }

10. En brugerdefineret matcher

Vi kan definere vores egen matcher ved at udvide TypeSafeMatcher. I dette afsnit opretter vi en brugerdefineret matcher, der kun tillader en test at bestå, når målet er et positivt heltal.

offentlig klasse IsPositiveInteger udvider TypeSafeMatcher {offentlig ugyldig beskrivelseTo (beskrivelse beskrivelse) {beskrivelse.appendText ("et positivt heltal"); } @Factory offentlig statisk Matcher isAPositiveInteger () {returner ny IsPositiveInteger (); } @ Override beskyttede boolske matches Sikkert (heltal) {return heltal> 0; }}

Vi behøver kun at implementere match sikkert metode, der kontrollerer, at målet faktisk er et positivt heltal og beskrive til metode, der frembringer en fejlmeddelelse, hvis testen ikke består.

Her er en test, der bruger vores nye tilpassede matcher:

@Test offentlig ugyldighed givenInteger_whenAPositiveValue_thenCorrect () {int num = 1; assertThat (num, isAPositiveInteger ()); }

og her er en fejlmeddelelse, vi får, siden vi har passeret i et ikke-positivt heltal:

java.lang.AssertionError: Forventes: et positivt heltal men: var 

11. Konklusion

I denne vejledning har vi det udforskede Hamcrest API og lærte, hvordan vi kan skrive bedre og mere vedligeholdelige enhedstest med det.

Den fulde implementering af alle disse eksempler og kodestykker kan findes i mit Hamcrest github-projekt.