JUnit 5 er den nye de facto standard til udvikling af enhedstest i Java. Denne nyeste version har efterladt begrænsningerne i Java 5 og integreret mange funktioner fra Java 8, især understøttelse af lambda-udtryk.
I denne første halvdel af en todelt introduktion til JUnit 5 kommer du i gang med test med JUnit 5. Jeg viser dig, hvordan du konfigurerer et Maven-projekt til at bruge JUnit 5, hvordan man skriver tests ved hjælp af @Prøve
og @ParameterizedTest
annoteringer, og hvordan man arbejder med de nye livscykluskommentarer i JUnit 5. Du får også vist et kort eksempel på brug af filterkoder, og jeg viser dig, hvordan du integrerer JUnit 5 med et tredjeparts påstandsbibliotek - i dette tilfælde , Hamcrest. Endelig får du en hurtig introduktion til tutorial til integration af JUnit 5 med Mockito, så du kan skrive mere robuste enhedstest til komplekse, virkelige systemer.
Test-drevet udvikling
Hvis du har udviklet Java-kode i nogen periode, er du sandsynligvis meget fortrolig med testdrevet udvikling, så jeg holder dette afsnit kort. Det er vigtigt at forstå hvorfor vi skriver dog enhedstests samt de strategier, som udviklere anvender, når de designer enhedstest.
Testdrevet udvikling (TDD) er en softwareudviklingsproces, der fletter kodning, test og design. Det er en test-første tilgang, der sigter mod at forbedre kvaliteten af dine applikationer. Testdrevet udvikling er defineret ved følgende livscyklus:
- Tilføj en test.
- Kør alle dine tests og observer den nye test mislykkes.
- Implementér koden.
- Kør alle dine tests, og følg den nye test, der følger.
- Refaktor koden.
Figur 1 viser denne TDD-livscyklus.
Steven HainesDer er et dobbelt formål med at skrive tests, før du skriver din kode. For det første tvinger det dig til at tænke over det forretningsproblem, du prøver at løse. For eksempel hvordan skal vellykkede scenarier opføre sig? Hvilke betingelser skal mislykkes? Hvordan skal de fejle? For det andet giver test først dig mere tillid til dine tests. Når jeg skriver tests efter at have skrevet kode, skal jeg altid bryde dem for at sikre, at de rent faktisk får fejl. Skrivetest undgår først dette ekstra trin.
At skrive prøver til den lykkelige sti er normalt let: I betragtning af gode input skal klassen returnere et deterministisk svar. Men at skrive negative (eller fiasko) testsager, især for komplekse komponenter, kan være mere kompliceret.
Overvej som et eksempel at skrive tests til et databaselager. På den glade sti indsætter vi en post i databasen og modtager det oprettede objekt tilbage, inklusive genererede nøgler. I virkeligheden skal vi også overveje muligheden for en konflikt, såsom at indsætte en post med en unik kolonneværdi, der allerede er indeholdt i en anden post. Derudover hvad sker der, når lageret ikke kan oprette forbindelse til databasen, måske fordi brugernavnet eller adgangskoden er ændret? Hvad sker der, hvis der er en netværksfejl under transit? Hvad sker der, hvis anmodningen ikke gennemføres i din definerede timeoutgrænse?
For at opbygge en robust komponent skal du overveje alle sandsynlige og usandsynlige scenarier, udvikle tests til dem og skrive din kode for at tilfredsstille disse tests. Senere i artiklen ser vi på strategier til oprettelse af forskellige fejlscenarier sammen med nogle af de nye funktioner i JUnit 5, der kan hjælpe dig med at teste disse scenarier.
Vedtagelse af JUnit 5
Hvis du har brugt JUnit i et stykke tid, vil nogle af ændringerne i JUnit 5 være en justering. Her er en oversigt på højt niveau af, hvad der er forskelligt mellem de to versioner:
- JUnit 5 er nu pakket i
org.junit.jupiter
gruppe, som ændrer, hvordan du inkluderer det i dine Maven- og Gradle-projekter. - JUnit 4 krævede et minimum JDK på JDK 5; JUnit 5 kræver mindst JDK 8.
- JUnit 4'er
@Før
,@BeforeClass
,@Efter
og@Efter skole
kommentarer er blevet erstattet af@BeforeEach
,@BeforeAll
,@AfterEach
og@Trods alt
, henholdsvis. - JUnit 4'er
@Ignorere
kommentar er blevet erstattet af@Handicappet
kommentar. - Det
@Kategori
kommentar er blevet erstattet af@Tag
kommentar. - JUnit 5 tilføjer et nyt sæt påståelsesmetoder.
- Løbere er blevet erstattet med udvidelser med en ny API til udvidelsesimplementatorer.
- JUnit 5 introducerer antagelser, der forhindrer en test i at udføre.
- JUnit 5 understøtter indlejrede og dynamiske testklasser.
Vi udforsker de fleste af disse nye funktioner i denne artikel.
Enhedstest med JUnit 5
Lad os starte simpelt med et end-to-end-eksempel på konfiguration af et projekt til at bruge JUnit 5 til en enhedstest. Liste 1 viser a MathTools
klasse, hvis metode konverterer en tæller og nævneren til en dobbelt
.
Liste 1. Et eksempel på et JUnit 5-projekt (MathTools.java)
pakke com.javaworld.geekcap.math; offentlig klasse MathTools {offentlig statisk dobbelt convertToDecimal (int tæller, int nævneren) {hvis (nævneren == 0) {kast ny IllegalArgumentException ("Nævneren må ikke være 0"); } returner (dobbelt) tæller / (dobbelt) nævneren; }}
Vi har to primære scenarier til test af MathTools
klasse og dens metode:
- EN gyldig test, hvor vi sender ikke-nul heltal for tælleren og nævneren.
- EN fejlscenarie, hvor vi sender en nulværdi for nævneren.
Liste 2 viser en JUnit 5 testklasse til test af disse to scenarier.
Annonce 2. En JUnit 5 testklasse (MathToolsTest.java)
pakke com.javaworld.geekcap.math; import java.lang.IllegalArgumentException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; klasse MathToolsTest {@Test ugyldig testConvertToDecimalSuccess () {dobbelt resultat = MathTools.convertToDecimal (3, 4); Assertions.assertEquals (0,75, resultat); } @Test ugyldig testConvertToDecimalInvalidDenominator () {Assertions.assertThrows (IllegalArgumentException.class, () -> MathTools.convertToDecimal (3, 0)); }}
I lister 2 er testConvertToDecimalInvalidDenominator
metoden udfører MathTools :: convertToDecimal
metode inde i en hævder kaster
opkald. Det første argument er den forventede type undtagelse, der skal kastes. Det andet argument er en funktion, der vil kaste denne undtagelse. Det hævder kaster
metode udfører funktionen og validerer, at den forventede type undtagelse kastes.
Assertions-klassen og dens metoder
Detorg.junit.jupiter.api.Test
annotation angiver en testmetode. Bemærk, at @Prøve
annotering kommer nu fra JUnit 5 Jupiter API-pakken i stedet for JUnit 4'er org.junit
pakke. Det testConvertToDecimalSuccess
metoden først udfører MathTools :: convertToDecimal
metode med tælleren 3 og nævneren 4, hævder derefter, at resultatet er lig med 0,75. Det org.junit.jupiter.api.Assertions
klasse giver et sæt af statisk
metoder til sammenligning af faktiske og forventede resultater. Det Påstande
klasse har følgende metoder, der dækker de fleste af de primitive datatyper:
assertArrayEquals
sammenligner indholdet af et faktisk array med et forventet array.hævderLige
sammenligner en faktisk værdi med en forventet værdi.assertNotEquals
sammenligner to værdier for at validere, at de ikke er ens.hævder sandt
validerer, at den angivne værdi er sand.hævder Falsk
validerer, at den angivne værdi er falsk.assertLinesMatch
sammenligner to lister overSnor
s.hævder Null
validerer, at den angivne værdi er nul.hævderNotNull
validerer, at den angivne værdi ikke er nul.hævderSamme
validerer, at to værdier henviser til det samme objekt.assertNotSame
validerer, at to værdier ikke henviser til det samme objekt.hævder kaster
validerer, at udførelsen af en metode giver en forventet undtagelse (du kan se dette itestConvertToDecimalInvalidDenominator
eksempel ovenfor).assertTimeout
validerer, at en leveret funktion gennemføres inden for en bestemt timeout.assertTimeoutForebyggende
validerer, at en leveret funktion fuldføres inden for en bestemt timeout, men når timeoutet er nået, dræber den funktionens udførelse.
Hvis nogen af disse påstandsmetoder mislykkes, markeres enhedstesten som mislykket. Denne fejlmeddelelse skrives til skærmen, når du kører testen, og gemmes derefter i en rapportfil.
Brug af delta med assertEquals
Ved brug flyde
og dobbelt
værdier i et hævderLige
, kan du også angive en delta
der repræsenterer en forskelstærskel mellem de to. I vores eksempel kunne vi have tilføjet et delta på 0,001, hvis 0,75 faktisk blev returneret som 0,750001.
Analyserer dine testresultater
Ud over at validere en værdi eller adfærd, hævde
metoder kan også acceptere en tekstbeskrivelse af fejlen, som kan hjælpe dig med at diagnosticere fejl. For eksempel:
Assertions.assertEquals (0,75, resultat, "MathTools :: convertToDecimal-værdien returnerede ikke den korrekte værdi på 0,75 for 3/4"); Assertions.assertEquals (0,75, resultat, () -> "MathTools :: convertToDecimal-værdien returnerede ikke den korrekte værdi på 0,75 for 3/4");
Outputtet viser den forventede værdi på 0,75 og den aktuelle værdi. Det viser også den angivne besked, som kan hjælpe dig med at forstå sammenhængen med fejlen. Forskellen mellem de to variationer er, at den første altid opretter meddelelsen, selvom den ikke vises, mens den anden kun konstruerer meddelelsen, hvis påstanden mislykkes. I dette tilfælde er opbygningen af meddelelsen triviel, så det betyder ikke rigtig noget. Der er stadig ikke behov for at konstruere en fejlmeddelelse til en test, der består, så det er normalt en bedste praksis at bruge den anden stil.
Endelig, hvis du bruger en IDE som IntelliJ til at køre dine tests, vil hver testmetode blive vist med dens metodenavn. Dette er fint, hvis dine metodenavne er læselige, men du kan også tilføje en @DisplayName
kommentar til dine testmetoder for bedre at identificere testene:
@Test @DisplayName ("Test succesfuld decimalkonvertering") ugyldig testConvertToDecimalSuccess () {dobbelt resultat = MathTools.convertToDecimal (3, 4); Assertions.assertEquals (0,751, resultat); }
Kører din enhedstest
For at køre JUnit 5-test fra et Maven-projekt skal du medtage maven-surefire-plugin
i Maven pom.xml
fil og tilføj en ny afhængighed. Liste 3 viser pom.xml
fil til dette projekt.
Annonce 3. Maven pom.xml for et eksempel på et JUnit 5-projekt
4.0.0 com.javaworld.geekcap junit5 jar 1.0-SNAPSHOT org.apache.maven.plugins maven-compiler-plugin 3.8.1 8 8 org.apache.maven.plugins maven-surefire-plugin 3.0.0-M4 junit5 // maven.apache.org org.junit.jupiter junit-jupiter 5.6.0 test
JUnit 5 afhængigheder
JUnit 5 pakker sine komponenter i org.junit.jupiter
gruppe, og vi skal tilføje junit-jupiter
artefakt, som er en sammenlægningsgenstand, der importerer følgende afhængigheder:
junit-jupiter-api
definerer API til skrivning af test og udvidelser.junit-jupiter-motor
er den implementering af testmotoren, der kører enhedstestene.junit-jupiter-params
giver support til parametriserede tests.
Dernæst skal vi tilføje maven-surefire-plugin
bygge plug-in for at køre testene.
Endelig skal du sørge for at medtage maven-compiler-plugin
med en version af Java 8 eller nyere, så du kan bruge Java 8-funktioner som lambdas.
Kør det!
Brug følgende kommando til at køre testklassen fra din IDE eller fra Maven:
mvn ren test
Hvis du har succes, skal du se output svarende til følgende:
[INFO] ------------------------------------------------------- -------- [INFO] TESTER [INFO] ----------------------------------- -------------------- [INFO] Kører com.javaworld.geekcap.math.MathToolsTest [INFO] Testkørsel: 2, Fejl: 0, Fejl: 0, springet over : 0, forløbet tid: 0,04 s - i com.javaworld.geekcap.math.MathToolsTest [INFO] [INFO] Resultater: [INFO] [INFO] Testkørsel: 2, Fejl: 0, Fejl: 0, Springet over: 0 [ INFO] [INFO] --------------------------------------------- --------------------------- [INFO] BYG SUCCES [INFO] --------------- -------------------------------------------------- ------- [INFO] Samlet tid: 3.832 s [INFO] Færdig kl .: 2020-02-16T08: 21: 15-05: 00 [INFO] ------------- -------------------------------------------------- ---------