En guide til JUnit 5

1. Oversikt

JUnit er en av de mest populære rammene for enhetstesting i Java-økosystemet. JUnit 5-versjonen inneholder en rekke spennende innovasjoner, med målet å støtte nye funksjoner i Java 8 og nyere, samt muliggjøre mange forskjellige teststiler.

2. Maven-avhengigheter

Å sette opp JUnit 5.x.0 er ganske greit, vi må legge til følgende avhengighet til vår pom.xml:

 org.junit.jupiter junit-jupiter-engine 5.1.0 test 

Det er viktig å merke seg at denne versjonen krever Java 8 for å fungere.

Dessuten er det nå direkte støtte for å kjøre enhetstester på JUnit-plattformen i Eclipse så vel som IntelliJ. Du kan selvfølgelig også kjøre tester med Maven Test-målet.

På den annen side støtter IntelliJ JUnit 5 som standard. Derfor er det ganske enkelt å kjøre JUnit 5 på IntelliJ, bare høyreklikk -> Kjør eller Ctrl-Shift-F10.

3. Arkitektur

JUnit 5 består av flere forskjellige moduler fra tre forskjellige delprosjekter:

3.1. JUnit-plattform

Plattformen er ansvarlig for å lansere testrammer på JVM. Den definerer et stabilt og kraftig grensesnitt mellom JUnit og klienten, for eksempel byggeverktøy.

Det endelige målet er hvordan kundene enkelt blir integrert med JUnit i å oppdage og utføre testene.

Den definerer også TestEngine API for å utvikle et testrammeverk som kjører på JUnit-plattformen. På den måten kan du plugge inn tredjeparts testbiblioteker, direkte til JUnit, ved å implementere tilpasset TestEngine.

3.2. JUnit Jupiter

Denne modulen inkluderer nye programmerings- og utvidelsesmodeller for å skrive tester i JUnit 5. Nye merknader i forhold til JUnit 4 er:

  • @TestFabrikk - betegner en metode som er en testfabrikk for dynamiske tester
  • @DisplayName - definerer tilpasset visningsnavn for en testklasse eller en testmetode
  • @Nestet - angir at den merkede klassen er en nestet, ikke-statisk testklasse
  • @Stikkord - erklærer koder for filtreringstester
  • @ExtendWith - den brukes til å registrere egendefinerte utvidelser
  • @BeforeEach - angir at den merkede metoden vil bli utført før hver testmetode (tidligere @Før)
  • @EfterEach - angir at den merkede metoden vil bli utført etter hver testmetode (tidligere @Etter)
  • @BeforeAll - angir at den merkede metoden vil bli utført før alle testmetodene i gjeldende klasse (tidligere @BeforeClass)
  • @Tross alt - angir at den merkede metoden vil bli utført etter alle testmetodene i gjeldende klasse (tidligere @Etter timen)
  • @Disable - den brukes til å deaktivere en testklasse eller metode (tidligere @Overse)

3.3. JUnit Vintage

Støtter å kjøre JUnit 3 og JUnit 4-baserte tester på JUnit 5-plattformen.

4. Grunnleggende merknader

For å diskutere nye kommentarer, delte vi seksjonen inn i følgende grupper, ansvarlige for utførelse: før testene, under testene (valgfritt) og etter testene:

4.1. @BeforeAll og @BeforeEach

Nedenfor er et eksempel på den enkle koden som skal utføres før hovedtestsakene:

@BeforeAll statisk ugyldig oppsett () {log.info ("@ BeforeAll - kjøres en gang før alle testmetodene i denne klassen"); } @BeforeEach void init () {log.info ("@ BeforeEach - utføres før hver testmetode i denne klassen"); }

Viktig å merke seg er at metoden med @BeforeAll merknader må være statiske, ellers kompilerer ikke koden.

4.2. @DisplayName og @Funksjonshemmet

La oss gå til nye test-valgfrie metoder:

@DisplayName ("Enkel test vellykket") @Test ugyldig testSingleSuccessTest () {log.info ("Suksess"); } @Test @Disabled ("Ikke implementert ennå") ugyldig testShowSomething () {}

Som vi kan se, kan vi endre visningsnavn eller deaktivere metoden med en kommentar ved å bruke nye kommentarer.

4.3. @EfterEach og @Tross alt

Til slutt, la oss diskutere metoder knyttet til operasjoner etter utførelse av tester:

@AfterEach ugyldig tearDown () {log.info ("@ AfterEach - utført etter hver testmetode."); } @AfterAll statisk ugyldig gjort () {log.info ("@ AfterAll - utført etter alle testmetoder."); }

Vær oppmerksom på denne metoden med @Tross alt må også være en statisk metode.

5. Påstander og antagelser

JUnit 5 prøver å dra full nytte av de nye funksjonene fra Java 8, spesielt lambda-uttrykk.

5.1. Påstander

Påstander er flyttet til org.junit.jupiter.api.Assertions og er forbedret betydelig. Som nevnt tidligere, kan du nå bruke lambdas i påstander:

@Test ugyldig lambdaExpressions () {assertTrue (Stream.of (1, 2, 3) .stream () .mapToInt (i -> i) .sum ()> 5, () -> "Sum skal være større enn 5" ); }

Selv om eksemplet ovenfor er trivielt, er en fordel ved å bruke lambda-uttrykket for påstandsmeldingen at det blir lat evaluert, noe som kan spare tid og ressurser hvis meldingen er kostbar.

Det er nå også mulig å gruppere påstander med assertAll () som vil rapportere eventuelle mislykkede påstander i gruppen med en MultipleFailuresError:

 @Test ugyldig groupAssertions () {int [] numbers = {0, 1, 2, 3, 4}; assertAll ("tall", () -> assertEquals (tall [0], 1), () -> assertEquals (tall [3], 3), () -> assertEquals (tall [4], 1)); }

Dette betyr at det nå er tryggere å komme med mer komplekse påstander, da du vil være i stand til å finne den nøyaktige plasseringen av feil.

5.2. Antagelser

Forutsetninger brukes kun til å kjøre tester hvis visse vilkår er oppfylt. Dette brukes vanligvis til eksterne forhold som er nødvendige for at testen skal kunne kjøres riktig, men som ikke er direkte relatert til det som testes.

Du kan erklære en antagelse med antar sant (), antar Falske (), og antar at().

@Test ugyldig trueAssumption () {antarTrue (5> 1); assertEquals (5 + 2, 7); } @Test ugyldig falseAssumption () {antar Falsk (5 assertEquals (2 + 2, 4)); }

Hvis en antagelse mislykkes, a TestAbortedException blir kastet og testen hoppes rett og slett over.

Antagelser forstår også lambdauttrykk.

6. Unntakstesting

Det er to måter for unntakstesting i JUnit 5. Begge kan implementeres ved hjelp av assertTrowes () metode:

@Test ugyldig shouldThrowException () {Throwable exception = assertThrows (UnsupportedOperationException.class, () -> {throw new UnsupportedOperationException ("Not supported");}); assertEquals (exception.getMessage (), "Ikke støttet"); } @Test ugyldig assertThrowsException () {String str = null; assertThrows (IllegalArgumentException.class, () -> {Integer.valueOf (str);}); }

Det første eksemplet brukes til å verifisere mer detaljer om det kastede unntaket, og det andre validerer bare typen unntak.

7. Test suiter

For å fortsette de nye funksjonene i JUnit 5, vil vi prøve å bli kjent med konseptet med å samle flere testklasser i en testpakke, slik at vi kan kjøre dem sammen. JUnit 5 gir to merknader: @SelectPackages og @SelectClasses for å lage testsuiter.

Husk at på dette tidlige stadiet støtter de fleste IDEer ikke disse funksjonene.

La oss ta en titt på den første:

@RunWith (JUnitPlatform.class) @SelectPackages ("com.baeldung") offentlig klasse AllUnitTest {}

@SelectPackage brukes til å spesifisere navnene på pakkene som skal velges når du kjører en testpakke. I vårt eksempel vil den kjøre all test. Den andre kommentaren, @SelectClasses, brukes til å spesifisere klassene som skal velges når du kjører en testpakke:

@RunWith (JUnitPlatform.class) @SelectClasses ({AssertionTest.class, AssumptionTest.class, ExceptionTest.class}) offentlig klasse AllUnitTest {}

For eksempel vil over klasse opprette en suite som inneholder tre testklasser. Vær oppmerksom på at klassene ikke trenger å være i en enkelt pakke.

8. Dynamiske tester

Det siste emnet vi ønsker å introdusere er JUnit 5 Dynamic Tests-funksjonen, som gjør det mulig å erklære og kjøre testtilfeller generert i løpetid. I motsetning til de statiske testene som definerer et fast antall testtilfeller på kompileringstidspunktet, tillater dynamiske tester oss å definere testtilfellet dynamisk i løpetiden.

Dynamiske tester kan genereres med en fabrikkmetode som er merket med @TestFabrikk. La oss ta en titt på kodeeksemplet:

@TestFactory public Stream translateDynamicTestsFromStream () {return in.stream () .map (word -> DynamicTest.dynamicTest ("Test translate" + word, () -> {int id = in.indexOf (word); assertEquals (out. få (id), oversette (ord));})); }

Dette eksemplet er veldig greit og lett å forstå. Vi ønsker å oversette ord med to ArrayList, navngitt i og ute, henholdsvis. Fabriksmetoden må returnere a Strøm, Samling, Iterabel, eller Iterator. I vårt tilfelle velger vi Java 8 Strøm.

Vær oppmerksom på at @TestFabrikk metoder må ikke være private eller statiske. Antall tester er dynamisk, og det avhenger av ArrayList størrelse.

9. Konklusjon

Oppskriften var en rask oversikt over endringene som kommer med JUnit 5.

Vi kan se at JUnit 5 har en stor endring i arkitekturen som relaterte seg til plattformstarter, integrering med byggeverktøy, IDE, andre enhetstestrammer osv. Videre er JUnit 5 mer integrert med Java 8, spesielt med Lambdas og Stream-konsepter .

Eksemplene som brukes i denne artikkelen finner du i GitHub-prosjektet.