Sprievodca knižnicou systémových pravidiel

1. Prehľad

Niekedy pri písaní testov jednotiek možno budeme musieť otestovať kód, ktorý interaguje priamo s Systém trieda. Spravidla v aplikáciách, ako sú napríklad nástroje príkazového riadku, ktoré volajú System.exit priamo alebo čítať argumenty pomocou System.in.

V tomto návode sa pozrieme na najbežnejšie vlastnosti úhľadnej externej knižnice s názvom System Rules, ktorá poskytuje sadu pravidiel JUnit na testovanie kódu, ktorý používa Systém trieda.

2. Maven závislosti

Najskôr do našej pridajme závislosť systémových pravidiel pom.xml:

 com.github.stefanbirkner systémové pravidlá 1.19.0 

Pridáme tiež závislosť System Lambda, ktorá je k dispozícii aj v Maven Central:

 com.github.stefanbirkner system-lambda 1.1.0 

Pretože systémové pravidlá priamo nepodporujú JUnit5, pridali sme poslednú závislosť. Toto poskytuje metódy obaľovania System Lambda, ktoré sa majú použiť v testoch. Existuje alternatíva založená na rozšíreniach, ktorá sa volá System Stubs.

3. Práca s vlastnosťami systému

Na rýchlu rekapituláciu platforma Java používa a Vlastnosti objekt poskytnúť informácie o lokálnom systéme a konfigurácii. Vlastnosti si môžeme jednoducho vytlačiť:

System.getProperties () .forEach ((kľúč, hodnota) -> System.out.println (kľúč + ":" + hodnota));

Ako vidíme, vlastnosti zahŕňajú informácie, ako napríklad aktuálny používateľ, aktuálna verzia runtime Java a oddeľovač názvu cesty k súboru:

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

Vlastné vlastnosti systému môžeme nastaviť aj pomocou znaku System.setProperty metóda. Pri práci s vlastnosťami systému z našich testov by ste mali byť opatrní, pretože tieto vlastnosti sú globálne JVM.

Napríklad, ak nastavíme systémovú vlastnosť, mali by sme sa ubezpečiť, že po dokončení testu alebo pri zlyhaní obnovíme vlastnosť na pôvodnú hodnotu. To môže niekedy viesť k ťažkopádnemu nastaveniu a strhnutiu kódu. Ak to však zanedbáme, mohlo by to v našich testoch viesť k neočakávaným vedľajším účinkom.

V nasledujúcej časti sa dozvieme, ako môžeme poskytnúť, vyčistiť a uistiť sa, že obnovíme hodnoty systémových vlastností po krátkom a jednoduchom dokončení našich testov.

4. Poskytnutie systémových vlastností

Poďme si predstaviť, že máme systémovú vlastnosť log_dir ktorý obsahuje umiestnenie, kam by sa mali zapisovať naše denníky, a naša aplikácia nastaví toto miesto pri spustení:

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

4.1. Poskytnite jednu nehnuteľnosť

Teraz zvážime, že z nášho testovania jednotiek chceme poskytnúť inú hodnotu. Môžeme to urobiť pomocou ProvideSystemProperty pravidlo:

verejná trieda ProvidesSystemPropertyWithRuleUnitTest {@Rule public final ProvideSystemProperty providesSystemPropertyRule = new ProvideSystemProperty ("log_dir", "test / resources"); @Test public void givenProvideSystemProperty_whenGetLogDir_thenLogDirIsProvidedSuccessfully () {assertEquals ("log_dir should be provided", "test / resources", System.getProperty ("log_dir")); } // definícia testu jednotky pokračuje} 

Pomocou ProvideSystemProperty pravidlo, môžeme nastaviť ľubovoľnú hodnotu pre danú systémovú vlastnosť na použitie z našich testov. V tomto príklade sme nastavili log_dir majetok k nášmu test / zdroje adresára az nášho testovania jednotiek jednoducho tvrdíme, že hodnota vlastnosti testu bola poskytnutá úspešne.

Ak si potom vytlačíme hodnotu log_dir vlastnosť po dokončení našej testovacej triedy:

@AfterClass public static void tearDownAfterClass () vyvolá výnimku {System.out.println (System.getProperty ("log_dir")); } 

Vidíme, že hodnota nehnuteľnosti bola obnovená na pôvodnú hodnotu:

/ tmp / baeldung / logs

4.2. Poskytovanie viacerých vlastností

Ak potrebujeme poskytnúť viac vlastností, môžeme použiť a metóda na spojenie toľko hodnôt vlastnosti, koľko požadujeme pre náš test:

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

4.3. Poskytovanie vlastností zo súboru

Rovnako tak máme možnosť poskytnúť vlastnosti zo súboru alebo prostriedku classpath pomocou súboru ProvideSystemProperty pravidlo:

@Rule public final ProvideSystemProperty providesSystemPropertyFromFileRule = ProvideSystemProperty.fromResource ("/ test.properties"); @Test public void givenProvideSystemPropertyFromFile_whenGetName_thenNameIsProvidedSuccessfully () {assertEquals ("treba uviesť meno", "baeldung", System.getProperty ("meno")); assertEquals ("verzia by mala byť poskytnutá", "1.0", System.getProperty ("verzia")); }

Vo vyššie uvedenom príklade predpokladáme, že máme a test.vlastnosti súbor na triednej ceste:

name = baeldung verzia = 1.0

4.4. Poskytovanie vlastností pomocou JUnit5 a Lambdas

Ako sme už spomenuli, na implementáciu testov kompatibilných s JUnit5 by sme mohli použiť aj verziu knižnice System Lambda.

Pozrime sa, ako implementovať náš test pomocou tejto verzie knižnice:

@BeforeAll static void setUpBeforeClass () vyvolá výnimku {System.setProperty ("log_dir", "/ tmp / baeldung / logs"); } @Test void daný ("log_dir"));}); assertEquals ("log_dir should be provided", "/ tmp / baeldung / logs", System.getProperty ("log_dir")); }

V tejto verzii môžeme použiť restoreSystemProperties metóda na vykonanie daného príkazu. V tomto vyhlásení môžeme nastaviť a poskytnúť hodnoty, ktoré požadujeme pre naše vlastnosti systému. Ako vidíme po dokončení tejto metódy, hodnota log_dir je rovnaká ako predtým / tmp / baeldung / logs.

Bohužiaľ neexistuje žiadna zabudovaná podpora pre poskytovanie vlastností zo súborov pomocou restoreSystemProperties metóda.

5. Vymazanie vlastností systému

Niekedy by sme mohli chcieť vyčistiť sadu systémových vlastností, keď sa spustí náš test, a obnoviť ich pôvodné hodnoty, keď sa test skončí, bez ohľadu na to, či vyhovuje alebo zlyhá.

Môžeme použiť ClearSystemProperties pravidlo na tento účel:

@ Pravidlo verejné konečné ClearSystemProperties userNameIsClearedRule = nové ClearSystemProperties ("user.name"); @ Test public void givenClearUsernameProperty_whenGetUserName_thenNull () {assertNull (System.getProperty ("user.name")); }

Vlastnosť systému meno používateľa je jednou z preddefinovaných vlastností systému, ktorá obsahuje názov používateľského účtu. Ako sa očakávalo vo vyššie uvedenom teste jednotky, vyčistíme túto vlastnosť a skontrolujeme, či je z nášho testu prázdna.

Pohodlne môžeme tiež odovzdať viac mien vlastností do ClearSystemProperties konštruktér.

6. Vysmievanie System.in

Z času na čas môžeme vytvoriť interaktívne aplikácie príkazového riadku, z ktorých sa bude čítať System.in.

V tejto časti použijeme veľmi jednoduchý príklad, ktorý načíta meno a priezvisko zo štandardného vstupu a spojí ich dohromady:

private String getFullname () {try (Scanner scanner = new Scanner (System.in)) {String firstName = scanner.next (); Reťazec priezvisko = scanner.next (); return String.join ("", meno, priezvisko); }}

Systémové pravidlá obsahujú TextFromStandardInputStream pravidlo, ktorým môžeme určiť linky, ktoré majú byť poskytované pri volaní System.in:

@ Pravidlo verejné konečné TextFromStandardInputStream systemInMock = prázdnyStandardInputStream (); @Test public void givenTwoNames_whenSystemInMock_thenNamesJoinedTogether () {systemInMock.provideLines ("Jonathan", "Cook"); assertEquals ("Mená by mali byť spojené", "Jonathan Cook", getFullname ()); }

Dosiahneme to použitím providesLines metóda, ktorá vyžaduje parameter varargs, aby umožnila špecifikáciu viac ako jednej hodnoty.

V tomto príklade poskytujeme dve hodnoty predtým, ako zavoláme getFullname metóda, kde System.in sa odkazuje. Naše dve poskytnuté hodnoty liniek sa vrátia zakaždým, keď zavoláme scanner.next ().

Poďme sa pozrieť na to, ako to môžeme dosiahnuť vo verzii JUnit 5 testu pomocou System Lambda:

@Test void dané }

V tejto variácii používame podobne pomenované withTextFromSystemIn metóda, ktorá nám umožňuje špecifikovať poskytnuté System.in hodnoty.

Je dôležité spomenúť v obidvoch prípadoch, že po ukončení testu sa pôvodná hodnota System.in budú obnovené.

7. Testovanie System.out a System.err

V predchádzajúcom tutoriáli sme videli, ako používať systémové pravidlá na testovanie jednotiek System.out.println ().

Pohodlne môžeme na testovanie kódu, ktorý interaguje so štandardným prúdom chýb, použiť takmer identický prístup. Tentokrát používame SystemErrRule:

@Rule public final SystemErrRule systemErrRule = nový SystemErrRule (). EnableLog (); @Test public void givenSystemErrRule_whenInvokePrintln_thenLogSuccess () {printError ("Vyskytla sa chyba Baeldung Readers !!"); Assert.assertEquals ("Došlo k chybe Baeldung Readers !!", systemErrRule.getLog (). Trim ()); } private void printError (výstup reťazca) {System.err.println (výstup); }

Pekný! Pomocou SystemErrRule, môžeme odpočúvať zápisy do System.err. Najskôr začneme zaznamenávať všetko, na čo je zapísané System.err zavolaním na enableLog metóda podľa nášho pravidla. Potom jednoducho zavoláme getLog aby sme napísali text na System.err, odkedy sme volali enableLog.

Teraz implementujme verziu nášho testu JUnit5:

@Test void givenTapSystemErr_whenInvokePrintln_thenOutputIsReturnedSuccessfully () vyvolá výnimku {String text = tapSystemErr (() -> {printError ("Došlo k chybe Baeldung Readers !!");}); Assert.assertEquals ("Došlo k chybe Baeldung Readers !!", text.trim ()); }

V tejto verzii využívame tapSystemErr metóda, ktorá vykoná príkaz a umožní nám zachytiť odovzdaný obsah System.err.

8. Manipulácia System.exit

Aplikácie príkazového riadku sa zvyčajne končia volaním System.exit. Ak chceme takúto aplikáciu otestovať, je pravdepodobné, že sa náš test nenormálne ukončí skôr, ako skončí, keď narazí na kód, ktorý volá System.exit.

Našťastie systémové pravidlá poskytujú prehľadné riešenie, ako to vyriešiť pomocou ExpectedSystemExit pravidlo:

@ Pravidlo verejné konečné ExpectedSystemExit exitRule = ExpectedSystemExit.none (); @Test public void givenSystemExitRule_whenAppCallsSystemExit_thenExitRuleWorkssAsExected () {exitRule.expectSystemExitWithStatus (1); východ(); } private void exit () {System.exit (1); }

Pomocou ExpectedSystemExit pravidlo nám umožňuje určiť z nášho testu očakávané System.exit () hovor. V tomto jednoduchom príklade tiež skontrolujeme očakávaný stavový kód pomocou znaku expectSystemExitWithStatus metóda.

Niečo podobné môžeme dosiahnuť v našej verzii JUnit 5 pomocou catchSystemExit metóda:

@Test void givenCatchSystemExit_whenAppCallsSystemExit_thenStatusIsReturnedSuccessfully () vyvolá výnimku {int statusCode = catchSystemExit (() -> {exit ();}); assertEquals ("stavový kód by mal byť 1:", 1, statusCode); }

9. Záver

Ak to zhrnieme, v tomto tutoriáli sme podrobne preskúmali knižnicu systémových pravidiel.

Najprv sme začali vysvetlením, ako testovať kód, ktorý využíva vlastnosti systému. Potom sme sa pozreli na to, ako otestovať štandardný výstup a štandardný vstup. Nakoniec sme sa pozreli na to, ako zaobchádzať s kódom, ktorý volá System.exit z našich testov.

Knižnica systémových pravidiel tiež poskytuje podporu pre poskytovanie premenných prostredia a špeciálnych bezpečnostných manažérov z našich testov. Podrobnosti nájdete v úplnej dokumentácii.

Celý zdrojový kód článku je ako vždy k dispozícii na GitHub.


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