Veiledning til systemreglerbiblioteket

1. Oversikt

Noen ganger når vi skriver enhetstester, kan det hende vi må teste kode som samhandler direkte med System klasse. Vanligvis i applikasjoner som kommandolinjeverktøy som ringer System.exit direkte eller les argumenter ved hjelp av System.in.

I denne veiledningen, Vi tar en titt på de vanligste funksjonene i et pent eksternt bibliotek kalt Systemregler som gir et sett med JUnit-regler for testing av kode som bruker System klasse.

2. Maven-avhengigheter

Først, la oss legge til avhengighet av systemregler til vår pom.xml:

 com.github.stefanbirkner systemregler 1.19.0 

Vi vil også legge til System Lambda-avhengighet som også er tilgjengelig fra Maven Central:

 com.github.stefanbirkner system-lambda 1.1.0 

Som Systemregler støtter ikke direkte JUnit5, har vi lagt til den siste avhengigheten. Dette gir System Lambda-innpakningsmetodene som skal brukes i tester. Det er et utvidelsesbasert alternativ til dette som kalles System Stubs.

3. Arbeide med systemegenskaper

For å raskt oppsummere bruker Java-plattformen en Eiendommer motsette seg for å gi informasjon om det lokale systemet og konfigurasjonen. Vi kan enkelt skrive ut egenskapene:

System.getProperties () .forEach ((nøkkel, verdi) -> System.out.println (nøkkel + ":" + verdi));

Som vi kan se, inkluderer egenskaper informasjon som den nåværende brukeren, den nåværende versjonen av Java-kjøretiden og skilletegn for filsti-navn:

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

Vi kan også sette våre egne systemegenskaper ved å bruke System.setProperty metode. Vær forsiktig når du arbeider med systemegenskaper fra testene våre, da disse egenskapene er JVM-globale.

Hvis vi for eksempel setter en systemegenskap, bør vi sørge for at vi gjenoppretter eiendommen til sin opprinnelige verdi når testen er ferdig eller hvis en feil oppstår. Dette kan noen ganger føre til tungvint oppsett og rive ned koden. Men hvis vi unnlater å gjøre dette, kan det føre til uventede bivirkninger i testene våre.

I neste avsnitt vil vi se hvordan vi kan tilby, rengjøre og sørge for at vi gjenoppretter systemegenskapsverdier etter at testene våre er fullført på en kort og enkel måte.

4. Tilby systemegenskaper

La oss forestille oss at vi har en systemegenskap log_dir som inneholder plasseringen der loggene våre skal skrives, og applikasjonen vår setter denne plasseringen når den starter:

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

4.1. Gi en enkelt eiendom

La oss nå vurdere at fra enhetstesten vil vi gi en annen verdi. Vi kan gjøre dette ved hjelp av Gi SystemProperty regel:

offentlig klasse ProvidesSystemPropertyWithRuleUnitTest {@Rule public final ProvideSystemProperty providesSystemPropertyRule = new ProvideSystemProperty ("log_dir", "test / resources"); @Test public void givenProvideSystemProperty_whenGetLogDir_thenLogDirIsProvidedSuccessfully () {assertEquals ("log_dir should be", "test / resources", System.getProperty ("log_dir")); } // enhetstestdefinisjon fortsetter} 

Bruker Gi SystemProperty regel kan vi sette en vilkårlig verdi for en gitt systemegenskap for bruk fra testene våre. I dette eksemplet setter vi log_dir eiendom til vår test / ressurser katalog, og fra vår enhetstest, hevder du bare at verdien for testegenskapen er gitt.

Hvis vi skriver ut verdien av log_dir egenskap når testklassen er fullført:

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

Vi kan se at verdien på eiendommen er gjenopprettet til sin opprinnelige verdi:

/ tmp / baeldung / logs

4.2. Tilbyr flere egenskaper

Hvis vi trenger å oppgi flere egenskaper, kan vi bruke og metode for å kjede så mange eiendomsverdier sammen som vi trenger for testen vår:

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

4.3. Tilby egenskaper fra en fil

På samme måte har vi også muligheten til å tilby egenskaper fra en fil eller klassesti-ressurs ved hjelp av Gi SystemProperty regel:

@Rule public final ProvideSystemProperty providesSystemPropertyFromFileRule = ProvideSystemProperty.fromResource ("/ test.properties"); @Test public void givenProvideSystemPropertyFromFile_whenGetName_thenNameIsProvidedSuccessfully () {assertEquals ("navn skal oppgis", "baeldung", System.getProperty ("navn")); assertEquals ("versjon skal gis", "1.0", System.getProperty ("versjon")); }

I eksemplet ovenfor antar vi at vi har en test.egenskaper fil på klassestien:

navn = baeldung versjon = 1.0

4.4. Tilby eiendommer med JUnit5 og Lambdas

Som vi tidligere nevnte, kunne vi også bruke System Lambda-versjonen av biblioteket til å implementere tester som er kompatible med JUnit5.

La oss se hvordan vi implementerer testen vår ved hjelp av denne versjonen av biblioteket:

@BeforeAll statisk ugyldig setUpBeforeClass () kaster unntak {System.setProperty ("log_dir", "/ tmp / baeldung / logs"); } @Test ugyldig givenSetSystemProperty_whenGetLogDir_thenLogDirIsProvidedSuccessfully () kaster unntak {gjenopprette SystemProperties (() -> {System.setProperty ("log_dir", "test / resources"); assertEquals ("log_dir skal være gitt", "test / ressurser,". ("log_dir"));}); assertEquals ("log_dir skal leveres", "/ tmp / baeldung / logs", System.getProperty ("log_dir")); }

I denne versjonen kan vi bruke gjenopprette SystemProperties metode for å utføre en gitt uttalelse. Inne i denne uttalelsen kan vi sette opp og gi verdiene vi trenger for systemegenskapene våre. Som vi kan se etter at denne metoden er ferdig med utførelsen, blir verdien av log_dir er det samme som før / tmp / baeldung / logs.

Dessverre er det ingen innebygd støtte for å tilby egenskaper fra filer som bruker gjenopprette SystemProperties metode.

5. Tømme systemegenskaper

Noen ganger kan det være lurt å fjerne et sett med systemegenskaper når testen starter og gjenopprette de opprinnelige verdiene når testen er ferdig, uavhengig av om den består eller mislykkes.

Vi kan bruke ClearSystemProperties regel for dette formålet:

@Rule public final ClearSystemProperties userNameIsClearedRule = new ClearSystemProperties ("user.name"); @Test offentlig ugyldig gittClearUsernameProperty_whenGetUserName_thenNull () {assertNull (System.getProperty ("user.name")); }

Systemegenskapen bruker.navn er en av de forhåndsdefinerte systemegenskapene, som inneholder brukerkontonavnet. Som forventet i ovenstående enhetstest, tømmer vi denne egenskapen og sjekker at den er tom fra testen vår.

Beleilig, vi kan også overføre flere eiendomsnavn til ClearSystemProperties konstruktør.

6. Hån System.in

Fra tid til annen kan vi lage interaktive kommandolinjeprogrammer som leser fra System.in.

For denne delen bruker vi et veldig enkelt eksempel som leser et fornavn og etternavn fra standardinngangen og sammenkobler dem sammen:

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

Systemregler inneholder TextFromStandardInputStream regel som vi kan bruke til å spesifisere linjene som skal oppgis når vi ringer System.in:

@ Regel offentlig endelig TextFromStandardInputStream systemInMock = tomStandardInputStream (); @Test offentlig ugyldighet gittTwoNames_whenSystemInMock_thenNamesJoinedTogether () {systemInMock.provideLines ("Jonathan", "Cook"); assertEquals ("Navn skal sammenkobles", "Jonathan Cook", getFullname ()); }

Vi oppnår dette ved å bruke providesLines metoden, som tar en varargs-parameter for å muliggjøre mer enn én verdi.

I dette eksemplet gir vi to verdier før vi kaller getFullname metode, hvor System.in er referert. Våre to angitte linjeverdier vil bli returnert hver gang vi ringer scanner.next ().

La oss se på hvordan vi kan oppnå det samme i en JUnit 5-versjon av testen ved hjelp av System Lambda:

@Test ugyldig givenTwoNames_whenSystemInMock_thenNamesJoinedTogether () kaster unntak {withTextFromSystemIn ("Jonathan", "Cook"). Execute (() -> {assertEquals ("Navn skal sammenkobles", "Jonathan Cook", getFullname ());}; }

I denne variasjonen bruker vi de samme navnene withTextFromSystemIn metode, som lar oss spesifisere den oppgitte System.in verdier.

Det er viktig å nevne i begge tilfeller at den opprinnelige verdien av etter at testen er fullført System.in vil bli gjenopprettet.

7. Testing System.out og System.err

I en tidligere opplæring så vi hvordan du bruker systemregler til enhetstest System.out.println ().

Praktisk kan vi bruke en nesten identisk tilnærming for testing av kode som samhandler med standard feilstrøm. Denne gangen bruker vi SystemErrRule:

@Rule offentlig slutt SystemErrRule systemErrRule = ny SystemErrRule (). EnableLog (); @Test offentlig ugyldig givenSystemErrRule_whenInvokePrintln_thenLogSuccess () {printError ("Det oppstod en feil Baeldung Lesere !!"); Assert.assertEquals ("Det oppstod en feil Baeldung Readers !!", systemErrRule.getLog (). Trim ()); } privat ugyldig utskriftError (String output) {System.err.println (output); }

Hyggelig! Bruker SystemErrRule, kan vi fange opp skriver til System.err. Først begynner vi å logge alt skrevet til System.err ved å ringe enableLog metode på vår regel. Så ringer vi rett og slett getLog for å få teksten skrevet til System.err siden vi ringte enableLog.

La oss nå implementere JUnit5-versjonen av testen vår:

@Test ugyldig givenTapSystemErr_whenInvokePrintln_thenOutputIsReturnedSuccessfully () kaster unntak {String text = tapSystemErr (() -> {printError ("Det oppstod en feil Baeldung Lesere !!");}); Assert.assertEquals ("Det oppstod en feil Baeldung Readers !!", text.trim ()); }

I denne versjonen, vi benytter oss av trykk på SystemErr metode, som kjører utsagnet og lar oss fange innholdet som sendes til System.err.

8. Håndtering System.exit

Kommandolinjeapplikasjoner avsluttes vanligvis ved å ringe System.exit. Hvis vi ønsker å teste en slik applikasjon, er det sannsynlig at testen vår avsluttes unormalt før den er ferdig når den møter koden som ringer System.exit.

Heldigvis gir systemregler en fin løsning for å håndtere dette ved hjelp av ExpectedSystemExit regel:

@Rule public final ExpectedSystemExit exitRule = ExpectedSystemExit.none (); @Test offentlig ugyldig gittSystemExitRule_whenAppCallsSystemExit_thenExitRuleWorkssAsExpected () {exitRule.expectSystemExitWithStatus (1); exit(); } privat tomromutgang () {System.exit (1); }

Bruker ExpectedSystemExit regelen lar oss spesifisere forventet fra testen System.exit () anrop. I dette enkle eksemplet sjekker vi også forventet statuskode ved hjelp av expectSystemExitWithStatus metode.

Vi kan oppnå noe lignende i vår JUnit 5-versjon ved hjelp av catchSystemExit metode:

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

9. Konklusjon

For å oppsummere har vi i denne opplæringen utforsket Systemregler-biblioteket i detalj.

Først begynte vi med å forklare hvordan vi kan teste kode som bruker systemegenskaper. Så så vi på hvordan vi kunne teste standardutgang og standardinngang. Til slutt så vi på hvordan vi skulle håndtere kode som ringer System.exit fra testene våre.

Systemregler-biblioteket gir også støtte for å tilby miljøvariabler og spesielle sikkerhetsmangere fra testene våre. Husk å sjekke ut hele dokumentasjonen for detaljer.

Som alltid er hele kildekoden til artikkelen tilgjengelig på GitHub.


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