Vejledning til JUnit 4-regler

1. Oversigt

I denne vejledning skal vi se på Regelfunktionen leveret af JUnit 4-biblioteket.

Vi begynder med at introducere JUnit Rules Model, før vi går igennem de vigtigste basisregler leveret af distributionen. Derudover vil vi også se, hvordan vi skriver og bruger vores egen brugerdefinerede JUnit-regel.

For at lære mere om test med JUnit, se vores omfattende JUnit-serie.

Bemærk, at hvis du bruger JUnit 5, er reglerne blevet erstattet af udvidelsesmodellen.

2. Introduktion til JUnit 4-regler

JUnit 4-regler giver en fleksibel mekanisme til at forbedre testene ved at køre noget kode omkring en eksekvering af en testsag. På en eller anden måde ligner det at have @Før og @Efter kommentarer i vores testklasse.

Lad os forestille os, at vi ønskede at oprette forbindelse til en ekstern ressource såsom en database under testopsætning og derefter lukke forbindelsen, når vores test er færdig. Hvis vi vil bruge denne database i flere tests, vil vi ende med at duplikere den kode i hver test.

Ved at bruge en regel kan vi have alt isoleret ét sted og genbruge koden let fra flere testklasser.

3. Brug af JUnit 4-regler

Så hvordan kan vi bruge regler? Vi kan bruge JUnit 4-regler ved at følge disse enkle trin:

  • Tilføj en offentlig felt til vores testklasse og sikre, at typen af ​​dette felt er en undertype af org.junit.rules.TestRule interface
  • Kommenter feltet med @Herske kommentar

I det næste afsnit ser vi, hvilke projektafhængigheder vi har brug for for at komme i gang.

4. Maven-afhængigheder

Lad os først tilføje de projektafhængigheder, vi har brug for til vores eksempler. Vi har kun brug for det primære JUnit 4-bibliotek:

 junit junit 4.12 

Som altid kan vi få den nyeste version fra Maven Central.

5. Regler leveret i distributionen

Selvfølgelig, JUnit leverer et antal nyttige, foruddefinerede regler som en del af biblioteket. Vi kan finde alle disse regler i org.junit.regler pakke.

I dette afsnit ser vi nogle eksempler på, hvordan du bruger dem.

5.1. Det Midlertidig mappe Herske

Når vi tester, har vi ofte brug for adgang til en midlertidig fil eller mappe. Administration af oprettelse og sletning af disse filer kan dog være besværlig. Bruger Midlertidig mappe regel kan vi styre oprettelsen af ​​filer og mapper, der skal slettes, når testmetoden afsluttes:

@Rule public TemporaryFolder tmpFolder = ny TemporaryFolder (); @Test offentlig ugyldighed givenTempFolderRule_whenNewFile_thenFileIsCreated () kaster IOException {File testFile = tmpFolder.newFile ("test-file.txt"); assertTrue ("Filen skulle være oprettet:", testFile.isFile ()); assertEquals ("Temp-mappe og testfil skal matche:", tmpFolder.getRoot (), testFile.getParentFile ()); }

Som vi kan se, definerer vi først Midlertidig mappe Herske tmpFolder. Dernæst opretter vores testmetode en fil, der hedder test-fil.txt i den midlertidige mappe. Vi kontrollerer derefter, at filen er oprettet og findes, hvor den skal. Virkelig flot og simpelt!

Når testen er færdig, skal den midlertidige mappe og fil slettes. Denne regel kontrollerer dog ikke, om sletningen er vellykket.

Der er også et par andre interessante metoder, der er værd at nævne i denne klasse:

  • newFile ()

    Hvis vi ikke giver noget filnavn, opretter denne metode en tilfældigt navngivet ny fil.

  • newFolder (String ... folderNames)

    For at oprette rekursivt dybe midlertidige mapper kan vi bruge denne metode.

  • ny mappe()

    Ligeledes ny mappe() metoden opretter en tilfældigt navngivet ny mappe.

En god tilføjelse, der er værd at nævne, er, at startende med version 4.13, Midlertidig mappe regel tillader verifikation af slettede ressourcer:

@Rule public TemporaryFolder folder = TemporaryFolder.builder (). AssureDeletion (). Build ();

Hvis en ressource ikke kan slettes, testes med fail med en Påstand Fejl.

Endelig kan vi i JUnit 5 opnå den samme funktionalitet ved hjælp af Temporary Directory-udvidelsen.

5.2. Det ExpectedException Herske

Som navnet antyder, vi kan bruge ExpectedException regel for at kontrollere, at nogle koder kaster en forventet undtagelse:

@ Regel offentlig endelig ExpectedException kastet = ExpectedException.none (); @Test offentlig ugyldighed givetIllegalArgument_whenExceptionThrown_MessageAndCauseMatches () {throw.expect (IllegalArgumentException.class); throw.expectCause (isA (NullPointerException.class)); throw.expectMessage ("Dette er ulovligt"); smid nyt IllegalArgumentException ("Dette er ulovligt", nyt NullPointerException ()); }

Som vi kan se i eksemplet ovenfor, erklærer vi først ExpectedException Herske. Så i vores test hævder vi, at en IllegalArgumentException kastes.

Ved hjælp af denne regel kan vi også kontrollere nogle andre egenskaber for undtagelsen, såsom meddelelsen og årsagen.

For en grundig vejledning til test af undtagelser med JUnit, se vores fremragende guide til, hvordan du hævder en undtagelse.

5.3. Det Testnavn Herske

Enkelt sagt, den Testnavn regel giver det aktuelle testnavn inde i en given testmetode:

@Rule offentligt testnavn navn = nyt testnavn (); @Test offentligt ugyldigt givetAddition_whenPrintingTestName_thenTestNameIsDisplayed () {LOG.info ("Executing: {}", name.getMethodName ()); assertEquals ("givenAddition_whenPrintingTestName_thenTestNameIsDisplayed", name.getMethodName ()); }

I dette trivielle eksempel, når vi kører enhedstesten, skal vi se testnavnet i output:

INFO c.baeldung.rules.JUnitRulesUnitTest - Executing: givenAddition_whenPrintingTestName_thenTestNameIsDisplayed

5.4. Det Tiden er gået Herske

I dette næste eksempel ser vi på Tiden er gået Herske. Denne regel giver et nyttigt alternativ til at bruge timeout-parameteren på en individuel testkommentar.

Lad os nu se, hvordan vi bruger denne regel til at indstille en global timeout på alle testmetoder i vores testklasse:

@Rule public Timeout globalTimeout = Timeout.seconds (10); @Test offentlig ugyldighed givenLongRunningTest_whenTimout_thenTestFails () kaster InterruptedException {TimeUnit.SECONDS.sleep (20); }

I ovenstående trivielle eksempel vi definerer først en global timeout for alle testmetoder på 10 sekunder. Derefter definerer vi bevidst en test, der tager længere tid end 10 sekunder.

Når vi kører denne test, skal vi se en testfejl:

org.junit.runners.model.TestTimedOutException: test blev udløbet efter 10 sekunder ...

5.5. Det ErrorCollector Herske

Næste gang skal vi se på ErrorCollector Herske. Denne regel tillader, at udførelsen af ​​en test fortsætter, efter at det første problem er fundet.

Lad os se, hvordan vi kan bruge denne regel til at indsamle alle fejlene og rapportere dem alle på én gang, når testen afsluttes:

@ Regel offentlig endelig ErrorCollector errorCollector = ny ErrorCollector (); @Test offentligt ugyldigt givetMultipleErrors_whenTestRuns_thenCollectorReportsErrors () {errorCollector.addError (ny Throwable ("Første ting gik galt!")); errorCollector.addError (ny Throwable ("En anden ting gik galt!"); errorCollector.checkThat ("Hello World", ikke (indeholderString ("FEJL!")); }

I ovenstående eksempel tilføjer vi to fejl til samleren. Når vi kører testen, fortsætter udførelsen, men testen mislykkes i slutningen.

I output ser vi begge rapporterede fejl:

java.lang.Trowable: Den første ting gik galt! ... java.lang.Trowable: En anden ting gik galt!

5.6. Det Verifikator Herske

Det Verifikator regel er en abstrakt basisklasse, som vi kan bruge, når vi ønsker at verificere yderligere adfærd fra vores tests. Faktisk er det ErrorCollector regel, vi så i det sidste afsnit, udvider denne klasse.

Lad os nu se på et trivielt eksempel på at definere vores egen verifikator:

privat liste messageLog = ny ArrayList (); @Rule public Verifier verifier = new Verifier () {@Override public void verific () {assertFalse ("Message Log is not Empty!", MessageLog.isEmpty ()); }}; 

Her definerer vi et nyt Verifikator og tilsidesætte verificere() metode til at tilføje nogle ekstra verifikationslogik. I dette enkle eksempel kontrollerer vi blot for at se, at meddelelsesloggen i vores eksempel ikke er tom.

Når vi kører enhedstesten og tilføjer en besked, skal vi se, at vores verifikator er blevet anvendt:

@Test offentligt ugyldigt givetNewMessage_whenVerified_thenMessageLogNotEmpty () {// ... messageLog.add ("Der er en ny besked!"); }

5.7. Det DisableOnDebug Herske

Nogle gange vil vi måske deaktivere en regel, når vi debugger. For eksempel er det ofte ønskeligt at deaktivere a Tiden er gået regere ved fejlretning for at undgå, at vores testtidspunkt udløber, og hvis vi ikke har haft tid til at fejle det korrekt.

Det DisableOnDebug Regel gør netop dette og giver os mulighed for at mærke visse regler, der skal deaktiveres, når debugging:

@Rule public DisableOnDebug disableTimeout = ny DisableOnDebug (Timeout.sekunder (30));

I eksemplet ovenfor kan vi se, at for at bruge denne regel, vi overfører simpelthen den regel, vi vil deaktivere, til konstruktøren.

Den største fordel ved denne regel er, at vi kan deaktivere regler uden at foretage ændringer i vores testklasser under fejlretning.

5.8. Det Ekstern ressource Herske

Når vi skriver integrationstests, ønsker vi typisk at oprette en ekstern ressource før en test og rive den bagefter. Heldigvis giver JUnit en anden praktisk baseklasse til dette.

Vi kan udvide den abstrakte klasse Ekstern ressource at opsætte en ekstern ressource før en test, såsom en fil eller en databaseforbindelse. Faktisk er det Midlertidig mappe regel, vi så tidligere, udvides Ekstern ressource.

Lad os se hurtigt på, hvordan vi kunne udvide denne klasse:

@Rule offentlig endelig ExternalResource externalResource = ny ExternalResource () {@Override beskyttet ugyldigt før () kaster Throwable {// kode for at opsætte en bestemt ekstern ressource. }; @ Override beskyttet ugyldigt efter () {// kode for at nedbryde den eksterne ressource}; };

I dette eksempel, når vi definerer en ekstern ressource, er vi bare nødt til at tilsidesætte Før() metode og efter() metode til at oprette og nedbryde vores eksterne ressource.

6. Anvendelse af klasseregler

Indtil nu har alle de eksempler, vi har set på, anvendt på enkelt test case-metoder. Men nogle gange vil vi måske anvende en regel på testklasseniveau. Vi kan opnå dette ved at bruge @ClassRule kommentar.

Denne kommentar fungerer meget ens @Herske men omslutter en regel omkring en hel test - den største forskel er, at det felt, vi bruger til vores klassestyring, skal være statisk:

@ClassRule offentlig statisk TemporaryFolder globalFolder = ny TemporaryFolder ();

7. Definition af en brugerdefineret JUnit-regel

Som vi har set, giver JUnit 4 en række nyttige regler ud af kassen. Selvfølgelig kan vi definere vores egne brugerdefinerede regler. For at skrive en brugerdefineret regel skal vi implementere Testregel interface.

Lad os se på et eksempel på at definere en brugerdefineret testmetode navneloggerregel:

offentlig klasse TestMethodNameLogger implementerer TestRule {privat statisk endelig Logger LOG = LoggerFactory.getLogger (TestMethodNameLogger.class); @ Override public Statement gælder (Erklæringsbase, Beskrivelse af beskrivelse) {logInfo ("Før test", beskrivelse); prøv {return new Statement () {@Override public void evaluere () kaster Throwable {base.evaluate (); }}; } endelig {logInfo ("Efter test", beskrivelse); }} privat ugyldig logInfo (String msg, Beskrivelse af beskrivelse) {LOG.info (msg + description.getMethodName ()) }}

Som vi kan se, er Testregel interface indeholder en kaldet metode anvende (erklæring, beskrivelse) at vi skal tilsidesætte for at returnere en forekomst af Udmelding. Erklæringen repræsenterer vores tests inden for JUnit runtime. Når vi kalder vurdere() metode, dette udfører vores test.

I dette eksempel logger vi en før og efter besked og inkluderer fra Beskrivelse gøre indsigelse mod metodens navn på den enkelte test.

8. Brug af regelkæder

I dette sidste afsnit vil vi se på, hvordan vi kan bestille flere testregler ved hjælp af RuleChain Herske:

@Rule public RuleChain chain = RuleChain.outerRule (new MessageLogger ("First rule")) .around (new MessageLogger ("Second rule")) .around (new MessageLogger ("Third rule"));

I ovenstående eksempel opretter vi en kæde med tre regler, der blot udskriver den meddelelse, der er sendt til hver MessageLogger konstruktør.

Når vi kører vores test, ser vi, hvordan kæden anvendes i rækkefølge:

Start: Første regel Start: Anden regel Start: Tredje regel Færdig: Tredje regel Færdig: Anden regel Færdig: Første regel

9. Konklusion

For at opsummere har vi i denne vejledning udforsket JUnit 4-regler i detaljer.

Først startede vi med at forklare, hvad regler er, og hvordan vi kan bruge dem. Dernæst kiggede vi grundigt på de regler, der kommer som en del af JUnit-distributionen.

Endelig så vi på, hvordan vi kan definere vores egen brugerdefinerede regel, og hvordan vi kæder regler sammen.

Som altid er artiklens fulde kildekode tilgængelig på GitHub.