Vejledning til systemreglerbiblioteket

1. Oversigt

Nogle gange når vi skriver enhedstest, er vi muligvis nødt til at teste kode, der interagerer direkte med System klasse. Typisk i applikationer som kommandolinjeværktøjer, der kalder System.exit direkte eller læs argumenter ved hjælp af System.in.

I denne vejledning Vi kigger på de mest almindelige funktioner i et pænt eksternt bibliotek kaldet Systemregler, der giver et sæt JUnit-regler til testkode, der bruger System klasse.

2. Maven-afhængigheder

Lad os først tilføje afhængigheden af ​​systemreglerne til vores pom.xml:

 com.github.stefanbirkner systemregler 1.19.0 

Vi tilføjer også System Lambda-afhængighed, som også er tilgængelig fra Maven Central:

 com.github.stefanbirkner system-lambda 1.1.0 

Da systemregler ikke understøtter direkte JUnit5, vi har tilføjet den sidste afhængighed. Dette giver System Lambda indpakningsmetoder, der kan bruges i test. Der er et udvidelsesbaseret alternativ til dette kaldet System Stubs.

3. Arbejde med systemegenskaber

For hurtigt at resumere bruger Java-platformen en Ejendomme gør indsigelse mod at give oplysninger om det lokale system og konfigurationen. Vi kan nemt udskrive egenskaberne:

System.getProperties () .forEach ((nøgle, værdi) -> System.out.println (nøgle + ":" + værdi));

Som vi kan se, inkluderer egenskaber information såsom den aktuelle bruger, den aktuelle version af Java-runtime og filstiensnavneseparator:

java.version: 1.8.0_221 file.separator: / user.home: / Brugere / baeldung os.name: Mac OS X ...

Vi kan også indstille vores egne systemegenskaber ved hjælp af System.setProperty metode. Vær forsigtig, når du arbejder med systemegenskaber fra vores tests, da disse egenskaber er JVM-globale.

For eksempel, hvis vi indstiller en systemegenskab, skal vi sikre, at vi gendanner ejendommen til dens oprindelige værdi, når vores test er færdig, eller hvis der opstår en fejl. Dette kan undertiden føre til besværlig opsætning og nedrivning af kode. Men hvis vi forsømmer at gøre dette, kan det føre til uventede bivirkninger i vores test.

I det næste afsnit ser vi, hvordan vi kan levere, rense og sikre, at vi gendanner systemegenskabsværdier, når vores tests er gennemført på en kortfattet og enkel måde.

4. Tilvejebringelse af systemegenskaber

Lad os forestille os, at vi har en systemegenskab log_dir som indeholder placeringen af, hvor vores logfiler skal skrives, og vores applikation indstiller denne placering, når den starter:

System.setProperty ("log_dir", "/ tmp / baeldung / logs");

4.1. Giv en enkelt ejendom

Lad os nu overveje, at vi fra vores enhedstest ønsker at give en anden værdi. Vi kan gøre dette ved hjælp af Giv SystemProperty Herske:

offentlig klasse ProvidesSystemPropertyWithRuleUnitTest {@Rule public final ProvideSystemProperty providesSystemPropertyRule = new ProvideSystemProperty ("log_dir", "test / resources"); @Test offentlig ugyldighed givenProvideSystemProperty_whenGetLogDir_thenLogDirIsProvidedSuccessfully () {assertEquals ("log_dir should be provided", "test / resources", System.getProperty ("log_dir")); } // enhedstestdefinition fortsætter} 

Bruger Giv SystemProperty regel kan vi indstille en vilkårlig værdi for en given systemegenskab til brug fra vores tests. I dette eksempel indstiller vi log_dir ejendom til vores test / ressourcer katalog, og fra vores enhedstest skal du blot hævde, at testegenskabsværdien er leveret med succes.

Hvis vi derefter udskriver værdien af log_dir egenskab når vores testklasse gennemføres:

@AfterClass offentlig statisk ugyldighed tearDownAfterClass () kaster undtagelse {System.out.println (System.getProperty ("log_dir")); } 

Vi kan se, at ejendommens værdi er gendannet til sin oprindelige værdi:

/ tmp / baeldung / logs

4.2. Tilvejebringelse af flere egenskaber

Hvis vi har brug for at levere flere egenskaber, kan vi bruge og metode til at kæde så mange egenskabsværdier sammen, som vi har brug for til vores test:

@Rule public final ProvideSystemProperty providesSystemPropertyRule = new ProvideSystemProperty ("log_dir", "test / resources"). Og ("another_property", "another_value")

4.3. Tilvejebringelse af egenskaber fra en fil

På samme måde har vi også muligheden for at levere egenskaber fra en fil- eller klassesti-ressource ved hjælp af Giv SystemProperty Herske:

@Rule public final ProvideSystemProperty providesSystemPropertyFromFileRule = ProvideSystemProperty.fromResource ("/ test.properties"); @Test offentlig ugyldighed givenProvideSystemPropertyFromFile_whenGetName_thenNameIsProvidedSuccessfully () {assertEquals ("navn skal gives", "baeldung", System.getProperty ("navn")); assertEquals ("version skal leveres", "1.0", System.getProperty ("version")); }

I ovenstående eksempel antager vi, at vi har en test.egenskaber fil på klassestien:

navn = baeldung version = 1.0

4.4. Udbyde ejendomme med JUnit5 og Lambdas

Som vi tidligere nævnte, kunne vi også bruge System Lambda-versionen af ​​biblioteket til at implementere tests, der er kompatible med JUnit5.

Lad os se, hvordan vi implementerer vores test ved hjælp af denne version af biblioteket:

@BeforeAll statisk ugyldig setUpBeforeClass () kaster undtagelse {System.setProperty ("log_dir", "/ tmp / baeldung / logs"); } @Test ugyldigt givenSetSystemProperty_whenGetLogDir_thenLogDirIsProvidedSuccessfully () kaster undtagelse {resetSystemProperties (() -> {System.setProperty ("log_dir", "test / ressourcer"); assertEquals ("log_dir skal tilvejebringes", "test / ressource)," ("log_dir"));}); assertEquals ("log_dir skal leveres", "/ tmp / baeldung / logs", System.getProperty ("log_dir")); }

I denne version kan vi bruge gendanne SystemProperties metode til at udføre en given erklæring. Inde i denne erklæring kan vi konfigurere og levere de værdier, vi har brug for til vores systemegenskaber. Som vi kan se, når denne metode er færdig med udførelsen, værdien af log_dir er den samme som før / tmp / baeldung / logs.

Desværre er der ingen indbygget support til at levere egenskaber fra filer ved hjælp af gendanne SystemProperties metode.

5. Rydning af systemegenskaber

Nogle gange vil vi muligvis rydde et sæt systemegenskaber, når vores test starter og gendanne deres oprindelige værdier, når testen er færdig, uanset om den består eller mislykkes.

Vi kan bruge ClearSystemProperties regel til dette formål:

@Rule offentlig endelig ClearSystemProperties userNameIsClearedRule = ny ClearSystemProperties ("user.name"); @Test offentligt ugyldigt givetClearUsernameProperty_whenGetUserName_thenNull () {assertNull (System.getProperty ("user.name")); }

Systemets egenskab bruger.navn er en af ​​de foruddefinerede systemegenskaber, som indeholder brugerkontonavnet. Som forventet i ovenstående enhedstest rydder vi denne egenskab og kontrollerer, at den er tom fra vores test.

Bekvemt kan vi også videregive flere ejendomsnavne til ClearSystemProperties konstruktør.

6. Hånende System.in

Fra tid til anden kan vi oprette interaktive kommandolinjeapplikationer, der læser fra System.in.

I dette afsnit bruger vi et meget simpelt eksempel, der læser et fornavn og efternavn fra standardindgangen og sammenkæder dem sammen:

private String getFullname () {try (Scannerscanner = ny Scanner (System.in)) {String firstName = scanner.next (); String efternavn = scanner.next (); returner String.join ("", fornavn, efternavn); }}

Systemregler indeholder TextFromStandardInputStream regel, som vi kan bruge til at specificere de linjer, der skal leveres, når vi ringer System.in:

@ Regel offentlig endelig TextFromStandardInputStream systemInMock = tomStandardInputStream (); @Test offentlig ugyldighed givenTwoNames_whenSystemInMock_thenNamesJoinedTogether () {systemInMock.provideLines ("Jonathan", "Cook"); assertEquals ("Navne skal sammenkædes", "Jonathan Cook", getFullname ()); }

Vi opnår dette ved hjælp af giver linjer metode, som tager en varargs-parameter for at muliggøre angivelse af mere end en værdi.

I dette eksempel giver vi to værdier, inden vi kalder getFullname metode, hvor System.in der henvises til. Vores to angivne linieværdier returneres hver gang vi ringer scanner.next ().

Lad os se på, hvordan vi kan opnå det samme i en JUnit 5-version af testen ved hjælp af System Lambda:

@Test ugyldigt givenTwoNames_whenSystemInMock_thenNamesJoinedTogether () kaster undtagelse {withTextFromSystemIn ("Jonathan", "Cook"). Execute (() -> {assertEquals ("Navne skal sammenkædes", "Jonathan Cook", getFullname ());}; }

I denne variation bruger vi det samme navngivne medTextFromSystemIn metode, som lader os specificere den leverede System.in værdier.

I begge tilfælde er det vigtigt at nævne, at den oprindelige værdi af efter test er afsluttet System.in vil blive gendannet.

7. Testning System.out og System.err

I en tidligere vejledning så vi, hvordan man bruger systemregler til enhedstest System.out.println ().

Bekvemt kan vi anvende en næsten identisk tilgang til testkode, der interagerer med standardfejlstrømmen. Denne gang bruger vi SystemErrRule:

@Rule offentlig endelig SystemErrRule systemErrRule = ny SystemErrRule (). EnableLog (); @Test offentlig ugyldighed givenSystemErrRule_whenInvokePrintln_thenLogSuccess () {printError ("Der opstod en fejl Baeldung-læsere !!"); Assert.assertEquals ("Der opstod en fejl Baeldung Readers !!", systemErrRule.getLog (). Trim ()); } privat ugyldigt printError (String output) {System.err.println (output); }

Pæn! Bruger SystemErrRule, kan vi opfange de skriver til System.err. Først begynder vi at logge alt skrevet til System.err ved at ringe til aktivere log metode på vores regel. Så ringer vi simpelthen getLog for at få teksten skrevet til System.err siden vi ringede aktivere log.

Lad os nu implementere JUnit5-versionen af ​​vores test:

@Test ugyldigt givenTapSystemErr_whenInvokePrintln_thenOutputIsReturnedSuccessfully () kaster undtagelse {String text = tapSystemErr (() -> {printError ("Der opstod en fejl Baeldung-læsere !!");}); Assert.assertEquals ("Der opstod en fejl Baeldung Readers !!", text.trim ()); }

I denne version, vi gør brug af tryk på SystemErr metode, der udfører erklæringen og lader os fange det indhold, der sendes til System.err.

8. Håndtering System.exit

Kommandolinjeapplikationer afsluttes typisk ved at ringe System.exit. Hvis vi vil teste en sådan applikation, er det sandsynligt, at vores test afsluttes unormalt, før den er færdig, når den møder den kode, der kalder System.exit.

Heldigvis giver systemregler en pæn løsning til at håndtere dette ved hjælp af ExpectedSystemExit Herske:

@Rule public final ExpectedSystemExit exitRule = ExpectedSystemExit.none (); @Test offentlig ugyldighed givenSystemExitRule_whenAppCallsSystemExit_thenExitRuleWorkssAsExpected () {exitRule.expectSystemExitWithStatus (1); Afslut(); } privat ugyldig afslutning () {System.exit (1); }

Bruger ExpectedSystemExit regel tillader os at specificere den forventede fra vores test System.exit () opkald. I dette enkle eksempel kontrollerer vi også den forventede statuskode ved hjælp af expectSystemExitWithStatus metode.

Vi kan opnå noget lignende i vores JUnit 5-version ved hjælp af catchSystemExit metode:

@Test ugyldigt givenCatchSystemExit_whenAppCallsSystemExit_thenStatusIsReturnedSuccessfully () kaster Undtagelse {int statusCode = catchSystemExit (() -> {exit ();}); assertEquals ("statuskode skal være 1:", 1, statusCode); }

9. Konklusion

For at opsummere har vi i denne vejledning udforsket biblioteket Systemregler i detaljer.

Først startede vi med at forklare, hvordan man tester kode, der bruger systemegenskaber. Derefter så vi på, hvordan man testede standardoutput og standardindgang. Endelig så vi på, hvordan man håndterer kode, der kalder op System.exit fra vores tests.

Systemregler-biblioteket understøtter også tilvejebringelse af miljøvariabler og specielle sikkerhedsmangere fra vores tests. Sørg for at tjekke den fulde dokumentation for detaljer.

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


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