En guide til JUnit 5

1. Oversigt

JUnit er en af ​​de mest populære rammer for enhedstest i Java-økosystemet. JUnit 5-versionen indeholder en række spændende innovationer med målet om at understøtte nye funktioner i Java 8 og nyeresamt muliggør mange forskellige testtyper.

2. Maven-afhængigheder

Opsætning af JUnit 5.x.0 er ret ligetil, vi skal tilføje følgende afhængighed til vores pom.xml:

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

Det er vigtigt at bemærke, at denne version kræver, at Java 8 fungerer.

Derudover er der nu direkte support til at køre enhedstest på JUnit-platformen i Eclipse såvel som IntelliJ. Du kan selvfølgelig også køre tests ved hjælp af Maven Test-målet.

På den anden side understøtter IntelliJ JUnit 5 som standard. Derfor er det ret simpelt at køre JUnit 5 på IntelliJ, bare højreklik -> Kør eller Ctrl-Shift-F10.

3. Arkitektur

JUnit 5 består af flere forskellige moduler fra tre forskellige delprojekter:

3.1. JUnit-platform

Platformen er ansvarlig for at lancere testrammer på JVM. Det definerer en stabil og kraftfuld grænseflade mellem JUnit og dens klient, såsom bygningsværktøjer.

Det endelige mål er, hvordan dets kunder let integreres med JUnit i at opdage og udføre testene.

Det definerer også TestEngine API til udvikling af en testramme, der kører på JUnit-platformen. Dermed kan du plug-in tredjeparts testbiblioteker direkte til JUnit ved at implementere brugerdefineret TestEngine.

3.2. JUnit Jupiter

Dette modul inkluderer nye programmerings- og udvidelsesmodeller til skrivning af test i JUnit 5. Nye kommentarer i sammenligning med JUnit 4 er:

  • @TestFabrik - angiver en metode, der er en testfabrik til dynamiske tests
  • @DisplayName - definerer brugerdefineret displaynavn for en testklasse eller en testmetode
  • @ Nestet - angiver, at den kommenterede klasse er en indlejret, ikke-statisk testklasse
  • @Tag - erklærer tags til filtreringstest
  • @ExtendWith - det bruges til at registrere brugerdefinerede udvidelser
  • @BeforeEach - angiver, at den kommenterede metode vil blive udført før hver testmetode (tidligere @Før)
  • @AfterEach - angiver, at den annoterede metode vil blive udført efter hver testmetode (tidligere @Efter)
  • @BeforeAll - angiver, at den annoterede metode vil blive udført før alle testmetoder i den aktuelle klasse (tidligere @BeforeClass)
  • @Trods alt - angiver, at den annoterede metode vil blive udført efter alle testmetoder i den aktuelle klasse (tidligere @Efter skole)
  • @Deaktiver - det bruges til at deaktivere en testklasse eller -metode (tidligere @Ignorere)

3.3. JUnit Vintage

Understøtter kørsel af JUnit 3 og JUnit 4 baserede tests på JUnit 5 platformen.

4. Grundlæggende kommentarer

For at diskutere nye kommentarer, delte vi sektionen i følgende grupper, der var ansvarlige for udførelse: før testene, under testene (valgfrit) og efter testene:

4.1. @BeforeAll og @BeforeEach

Nedenfor er et eksempel på den enkle kode, der skal udføres før de vigtigste testsager:

@BeforeAll opsætning af statisk ugyldighed () {log.info ("@ BeforeAll - udføres en gang før alle testmetoder i denne klasse"); } @BeforeEach ugyldigt init () {log.info ("@ BeforeEach - udføres før hver testmetode i denne klasse"); }

Vigtigt at bemærke er, at metoden med @BeforeAll annotering skal være statisk, ellers kompilerer koden ikke.

4.2. @DisplayName og @Handicappet

Lad os gå til nye test-valgfri metoder:

@DisplayName ("Enkel test vellykket") @Test ugyldig testSingleSuccessTest () {log.info ("Succes"); } @Test @Disabled ("Ikke implementeret endnu") ugyldig testShowSomething () {}

Som vi kan se, kan vi ændre skærmnavn eller deaktivere metoden med en kommentar ved hjælp af nye kommentarer.

4.3. @AfterEach og @Trods alt

Lad os endelig diskutere metoder forbundet til operationer efter testudførelse:

@AfterEach ugyldigt tearDown () {log.info ("@ AfterEach - udført efter hver testmetode."); } @AfterAll statisk ugyldigt gjort () {log.info ("@ AfterAll - udført efter alle testmetoder."); }

Bemærk denne metode med @Trods alt skal også være en statisk metode.

5. Påstande og antagelser

JUnit 5 forsøger at drage fuld fordel af de nye funktioner fra Java 8, især lambda-udtryk.

5.1. Påstande

Påstande er flyttet til org.junit.jupiter.api.Assertions og er blevet forbedret betydeligt. Som nævnt tidligere kan du nu bruge lambdas i påstande:

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

Selvom eksemplet ovenfor er trivielt, er en fordel ved at bruge lambda-udtrykket til påstandsmeddelelsen, at det dovles med at blive evalueret, hvilket kan spare tid og ressourcer, hvis meddelelseskonstruktionen er dyr.

Det er nu også muligt at gruppere påstande med hævderAlle () som rapporterer eventuelle mislykkede påstande inden for gruppen med en MultipleFailuresError:

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

Det betyder, at det nu er sikrere at komme med mere komplekse påstande, da du vil være i stand til at lokalisere den nøjagtige placering af enhver fejl.

5.2. Antagelser

Antagelser bruges kun til at køre tests, hvis visse betingelser er opfyldt. Dette bruges typisk til eksterne forhold, der kræves for at testen kan køre korrekt, men som ikke er direkte relateret til det, der testes.

Du kan erklære en antagelse med antage sandt (), antage Falsk ()og antager, at ().

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

Hvis en antagelse mislykkes, a TestAbortedException kastes, og testen springes simpelthen over.

Antagelser forstår også lambda-udtryk.

6. Undtagelsestest

Der er to måder til undtagelsestest i JUnit 5. Begge kan implementeres ved hjælp af assertTrow () metode:

@Test ugyldigt shouldThrowException () {Throwable exception = assertThrows (UnsupportedOperationException.class, () -> {throw new UnsupportedOperationException ("Not understøttet");}); assertEquals (exception.getMessage (), "Understøttes ikke"); } @Test ugyldigt assertThrowsException () {String str = null; assertThrows (IllegalArgumentException.class, () -> {Integer.valueOf (str);}); }

Det første eksempel bruges til at verificere flere detaljer af den kastede undtagelse, og det andet validerer bare typen af ​​undtagelse.

7. Test suiter

For at fortsætte de nye funktioner i JUnit 5 vil vi forsøge at lære begrebet at samle flere testklasser i en testpakke, så vi kan køre dem sammen. JUnit 5 indeholder to kommentarer: @SelectPackages og @SelectClasses at oprette testpakker.

Husk, at de fleste IDE'er på dette tidlige tidspunkt ikke understøtter disse funktioner.

Lad os se på den første:

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

@SelectPackage bruges til at specificere navnene på pakker, der skal vælges, når du kører en testpakke. I vores eksempel kører det alle test. Den anden kommentar, @SelectClasses, bruges til at specificere de klasser, der skal vælges, når du kører en testpakke:

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

For eksempel opretter ovenstående klasse en suite, der indeholder tre testklasser. Bemærk, at undervisningen ikke behøver at være i en enkelt pakke.

8. Dynamiske tests

Det sidste emne, som vi vil introducere, er JUnit 5 Dynamic Tests-funktionen, som gør det muligt at erklære og køre testcases genereret ved kørselstid. I modsætning til de statiske tests, der definerer et fast antal testsager på kompileringstidspunktet, giver de dynamiske tests os mulighed for at definere testsagen dynamisk i løbetiden.

Dynamiske tests kan genereres ved en fabriksmetode, der er kommenteret med @TestFabrik. Lad os se på kodeeksemplet:

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

Dette eksempel er meget ligetil og let at forstå. Vi vil oversætte ord ved hjælp af to ArrayList, som hedder i og ud, henholdsvis. Fabriksmetoden skal returnere a Strøm, Kollektion, Iterabel, eller Iterator. I vores tilfælde vælger vi Java 8 Strøm.

Bemærk, at @TestFabrik metoder må ikke være private eller statiske. Antallet af tests er dynamisk, og det afhænger af ArrayList størrelse.

9. Konklusion

Opskrivningen var et hurtigt overblik over de ændringer, der kommer med JUnit 5.

Vi kan se, at JUnit 5 har en stor ændring i sin arkitektur, der relaterede til platformstarter, integration med build-værktøj, IDE, andre enhedstestrammer osv. Desuden er JUnit 5 mere integreret med Java 8, især med Lambdas og Stream-koncepter .

Eksemplerne i denne artikel kan findes i GitHub-projektet.