Testing med Hamcrest

1. Oversikt

Hamcrest er det velkjente rammeverket som brukes til enhetstesting i Java-økosystemet. Den er samlet i JUnit og enkelt sagt, den bruker eksisterende predikater - kalt matcherklasser - for å komme med påstander.

I denne opplæringen vil vi utforsk Hamcrest API og lære hvordan du kan dra nytte av det til å skrive bedre og mer intuitive enhetstester for programvaren vår.

2. Oppsett av Hamcrest

Vi kan bruke Hamcrest med maven ved å legge til følgende avhengighet til vår pom.xml fil:

 org.hamcrest hamcrest-all 1.3 

Den siste versjonen av dette biblioteket finner du alltid her.

3. Et eksempel på en test

Hamcrest brukes ofte med junit og andre testrammer for påstander. Spesielt i stedet for å bruke junitEr mange hevder metoder bruker vi bare API-ene hevder det uttalelse med passende matchere.

La oss se på et eksempel som tester to Strings for likestilling uavhengig av sak. Dette skal gi oss en klar ide om hvordan Hamcrest passer inn i en testmetode:

offentlig klasse StringMatcherTest {@Test offentlig ugyldighet gitt2Strings_whenEqual_thenCorrect () {String a = "foo"; Streng b = "FOO"; assertThat (a, equalToIgnoringCase (b)); }}

I de følgende avsnittene vil vi se på flere andre vanlige matchere Hamcrest tilbud.

4. Den Gjenstand Matcher

Hamcrest gir matchere for å gjøre påstander om vilkårlige Java-objekter.

Å hevde at toString metode for en Gjenstand returnerer en spesifisert String:

@Test offentlig ugyldig givenBean_whenToStringReturnsRequiredString_thenCorrect () {Person person = new Person ("Barrack", "Washington"); Strengstr = person.toString (); assertThat (person, hasToString (str)); }

Vi kan også sjekke at en klasse er en underklasse av en annen:

@Test offentlig ugyldig gitt2Classes_whenOneInheritsFromOther_thenCorrect () {assertThat (Cat.class, typeCompatibleWith (Animal.class)); }}

5. The Bean Matcher

Vi kan bruke Hamcrest‘S Bean matcher for å inspisere egenskaper til en Java bønne.

Anta følgende Person bønne:

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

Vi kan sjekke om bønnen har eiendommen, Navn som så:

@Test offentlig ugyldig givenBean_whenHasValue_thenCorrect () {Person person = new Person ("Baeldung", 25); assertThat (person, hasProperty ("navn")); }

Vi kan også sjekke om Person har adresse eiendom, initialisert til New York:

@Test offentlig ugyldighet gittBean_whenHasCorrectValue_thenCorrect () {Person person = new Person ("Baeldung", "New York"); assertThat (person, hasProperty ("adresse", equalTo ("New York"))); }

Vi kan like godt sjekke om to Person objekter er konstruert med de samme verdiene:

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

6. Den Samling Matcher

Hamcrest gir matchere for inspeksjon Samlings.

Enkel sjekk for å finne ut om en Samling er tom:

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

For å sjekke størrelsen på en Samling:

@Test offentlig tomrom gittAList_whenChecksSize_thenCorrect () {List hamcrestMatchers = Arrays.asList ("samlinger", "bønner", "tekst", "nummer"); assertThat (hamcrestMatchers, hasSize (4)); }

Vi kan også bruke den til å hevde at en matrise har den nødvendige størrelsen:

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

For å sjekke om en Samling inneholder gitte medlemmer, uavhengig av rekkefølge:

@Test offentlig ugyldig gittAListAndValues_whenChecksListForGivenValues_thenCorrect () {List hamcrestMatchers = Arrays.asList ("samlinger", "bønner", "tekst", "nummer"); assertThat (hamcrestMatchers, inneholderInAnyOrder ("bønner", "tekst", "samlinger", "nummer")); }

For ytterligere å hevde at Samling medlemmene er i gitt rekkefølge:

@Test offentlig ugyldig gittAListAndValues_whenChecksListForGivenValuesWithOrder_thenCorrect () {List hamcrestMatchers = Arrays.asList ("samlinger", "bønner", "tekst", "nummer"); assertThat (hamcrestMatchers, inneholder ("samlinger", "bønner", "tekst", "nummer")); }

Slik sjekker du om en matrise har et enkelt gitt element:

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

Vi kan også bruke en alternativ matcher for samme test:

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

Eller fortsatt kan vi gjøre det samme med en annen matcher slik:

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

Vi kan også sjekke om matrisen inneholder gitte elementer uavhengig av rekkefølge:

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

For å sjekke om matrisen inneholder gitte elementer, men i den angitte rekkefølgen:

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

Når vår Samling er en Kart, vi kan bruke følgende matchere i disse respektive funksjonene:

Slik sjekker du om den inneholder en gitt nøkkel:

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

og en gitt verdi:

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

og til slutt en gitt oppføring (nøkkel, verdi):

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

7. Den Nummer Matcher

De Nummer matchere brukes til å utføre påstander om variabler av Nummer klasse.

Å sjekke større enn tilstand:

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

Å sjekke større enn eller lik tilstand:

@Test offentlig ugyldig givenAnInteger_whenGreaterThanOrEqTo5_thenCorrect () {assertThat (5, greaterThanOrEqualTo (5)); }

Å sjekke mindre enn tilstand:

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

Å sjekke mindre enn eller lik tilstand:

@Test offentlig ugyldig givenAnInteger_whenLessThanOrEqTo5_thenCorrect () {assertThat (-1, lessThanOrEqualTo (5)); }

Å sjekke nærme tilstand:

@Test offentlig ugyldighet gittADouble_whenCloseTo_thenCorrect () {assertThat (1.2, closeTo (1, 0.5)); }

La oss være nøye med den siste matcheren, nærme. Det første argumentet, operanden, er det som målet sammenlignes med, og det andre argumentet er det tillatte avviket fra operanden . Dette betyr at hvis målet er operand + avvik eller operand-avvik, så vil testen bestå.

8. Tekstmatcheren

Påstand om Strings er gjort enklere, penere og mer intuitivt med Hamcrest‘S text matchers. Vi kommer til å se på dem i denne delen.

For å sjekke om en String er tom:

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

For å sjekke om en String er tom eller null:

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

Å sjekke om det er to like Strings mens du ignorerer hvite mellomrom:

@Test offentlig ugyldig gitt2Strings_whenEqualRegardlessWhiteSpace_thenCorrect () {String str1 = "text"; String str2 = "text"; assertThat (str1, equalToIgnoringWhiteSpace (str2)); }

Vi kan også sjekke om det er en eller flere understrenger i en gitt String i en gitt rekkefølge:

@Test offentlig ugyldig givenString_whenContainsGivenSubstring_thenCorrect () {String str = "kalligrafi"; assertThat (str, stringContainsInOrder (Arrays.asList ("call", "graph"))); }

Til slutt kan vi sjekke om det er to likeverd Strings uansett sak:

@Test offentlig ugyldighet gitt2Strings_whenEqual_thenCorrect () {String a = "foo"; Streng b = "FOO"; assertThat (a, equalToIgnoringCase (b)); }

9. Core API

De Hamcrest core API skal brukes av tredjeparts rammeleverandører. Imidlertid gir det oss noen gode konstruksjoner for å gjøre enhetstestene våre mer lesbare og også noen kjernematchere som kan brukes like enkelt.

Lesbarhet med er konstruer på en matcher:

@Test offentlig ugyldighet gitt2Strings_whenIsEqualRegardlessWhiteSpace_thenCorrect () {String str1 = "text"; String str2 = "text"; assertThat (str1, er (equalToIgnoringWhiteSpace (str2))); }

De er konstruere på en enkel datatype:

@Test offentlig ugyldig given2Strings_whenIsEqual_thenCorrect () {String str1 = "text"; String str2 = "text"; assertThat (str1, er (str2)); }

Negasjon med ikke konstruer på en matcher:

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

De ikke konstruere på en enkel datatype:

@Test offentlig ugyldig given2Strings_whenNotEqual_thenCorrect () {String str1 = "text"; String str2 = "tekster"; hevder at (str1, ikke (str2)); }

Sjekk om en String inneholder en gitt understreng:

@Test offentlig ugyldighet gittAStrings_whenContainsAnotherGivenString_thenCorrect () {String str1 = "kalligrafi"; String str2 = "call"; assertThat (str1, inneholderString (str2)); }

Sjekk om en String starter med gitt understreng:

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

Sjekk om en String slutter med gitt understreng:

@Test offentlig ugyldighet gittAString_whenEndsWithAnotherGivenString_thenCorrect () {String str1 = "kalligrafi"; Streng str2 = "phy"; assertThat (str1, endsWith (str2)); }

Sjekk om to Gjenstands er av samme forekomst:

@Test offentlig ugyldighet gitt2Objects_whenSameInstance_thenCorrect () {Cat cat = new Cat (); assertThat (cat, sameInstance (cat)); }

Sjekk om en Gjenstand er en forekomst av en gitt klasse:

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

Sjekk om alle medlemmer av a Samling oppfylle en forutsetning:

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

Sjekk at en String er ikke null:

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

Kjedeforhold sammen, test går når målet oppfyller noen av betingelsene, i likhet med logisk ELLER:

@Test offentlig ugyldighet gittString_whenMeetsAnyOfGivenConditions_thenCorrect () {String str = "kalligrafi"; String start = "call"; String end = "foo"; assertThat (str, anyOf (startsWith (start), containString (end))); }

Kjedeforhold sammen, testen går bare når målet oppfyller alle betingelser, i likhet med logiske OG:

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

10. En tilpasset matcher

Vi kan definere vår egen matcher ved å utvide TypeSafeMatcher. I denne delen vil vi lage en tilpasset matcher som lar en test bare bestå når målet er et positivt heltall.

offentlig klasse IsPositiveInteger utvider TypeSafeMatcher {offentlig ugyldig beskrivelseTo (beskrivelse av beskrivelse) {beskrivelse.appendText ("et positivt heltall"); } @Factory public static Matcher isAPositiveInteger () {return new IsPositiveInteger (); } @ Override-beskyttede boolske treff Sikkert (heltall) {retur heltall> 0; }}

Vi trenger bare å implementere matchSikkert metode som sjekker at målet faktisk er et positivt heltall og beskriv til metode som gir en feilmelding i tilfelle testen ikke består.

Her er en test som bruker vår nye tilpassede matcher:

@Test offentlig ugyldighet gittInteger_whenAPositiveValue_thenCorrect () {int num = 1; assertThat (num, isAPositiveInteger ()); }

og her er en feilmelding vi får siden vi har passert i et ikke-positivt heltall:

java.lang.AssertionError: Forventet: et positivt heltall men: var 

11. Konklusjon

I denne opplæringen har vi det utforsket Hamcrest API og lærte hvordan vi kan skrive bedre og mer vedlikeholdbare enhetstester med det.

Full implementering av alle disse eksemplene og kodebiter finner du i mitt Hamcrest github-prosjekt.


$config[zx-auto] not found$config[zx-overlay] not found