Vodič kroz knjižnicu sistemskih pravila

1. Pregled

Ponekad prilikom pisanja jediničnih testova možda ćemo morati testirati kod koji izravno komunicira s Sustav razred. Tipično u aplikacijama kao što su alati naredbenog retka koji pozivaju System.exit izravno ili pročitajte argumente koristeći System.in.

U ovom vodiču, pogledati ćemo najčešće karakteristike uredne vanjske knjižnice nazvane System Rules koja pruža skup JUnit pravila za testiranje koda koji koristi Sustav razred.

2. Ovisnosti Mavena

Prvo, dodajmo ovisnost o sistemskim pravilima na našu pom.xml:

 com.github.stefanbirkner sustav-pravila 1.19.0 

Također ćemo dodati System Lambda ovisnost koja je dostupna i od Maven Central:

 com.github.stefanbirkner system-lambda 1.1.0 

Kao što Pravila sustava ne podržavaju izravno JUnit5, dodali smo zadnju ovisnost. To pruža metode omotača sustava Lambda koje se koriste u testovima. Postoji alternativa zasnovana na proširenjima koja se naziva Sistemske grebice.

3. Rad sa svojstvima sustava

Za brzo sažimanje, Java platforma koristi Svojstva objekt za pružanje informacija o lokalnom sustavu i konfiguraciji. Svojstva možemo lako isprintati:

System.getProperties () .forEach ((ključ, vrijednost) -> System.out.println (ključ + ":" + vrijednost));

Kao što vidimo, svojstva uključuju informacije poput trenutnog korisnika, trenutne verzije Java runtime-a i separatora imena puta datoteke:

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

Također možemo postaviti vlastita svojstva sustava pomoću System.setProperty metoda. Treba biti oprezan pri radu sa svojstvima sustava iz naših testova, jer su ta svojstva JVM-globalna.

Na primjer, ako postavimo svojstvo sustava, trebali bismo osigurati da svojstvo vratimo na izvornu vrijednost kada se test završi ili ako se dogodi kvar. To ponekad može dovesti do glomaznog postavljanja i rušenja koda. Međutim, ako to zanemarimo, to bi moglo dovesti do neočekivanih nuspojava u našim testovima.

U sljedećem ćemo odjeljku vidjeti kako možemo osigurati, očistiti i osigurati da vratimo vrijednosti svojstava sustava nakon što se testovi završe na sažet i jednostavan način.

4. Pružanje svojstava sustava

Zamislimo da imamo svojstvo sustava log_dir koji sadrži mjesto na kojem bi trebali biti napisani naši dnevnici i naša aplikacija postavlja ovo mjesto kad se pokrene:

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

4.1. Navedite jedno svojstvo

Sada uzmimo u obzir da iz našeg jediničnog testa želimo pružiti drugačiju vrijednost. To možemo učiniti pomoću ProvideSystemProperty Pravilo:

javna klasa ProvidesSystemPropertyWithRuleUnitTest {@Rule javno konačno ProvideSystemProperty dajeSystemPropertyRule = novo ProvideSystemProperty ("log_dir", "test / resources"); @Test javna praznina givenProvideSystemProperty_whenGetLogDir_thenLogDirIsProvidedSuccessfully () {assertEquals ("log_dir treba navesti", "test / resources", System.getProperty ("log_dir")); } // nastavlja se definicija jediničnog testa} 

Koristiti ProvideSystemProperty pravilo, možemo postaviti proizvoljnu vrijednost za dano svojstvo sustava za upotrebu iz naših testova. U ovom primjeru postavljamo log_dir vlasništvo našem test / resursi direktorija i iz našeg jediničnog testa jednostavno ustvrdite da je vrijednost svojstva testa uspješno pružena.

Ako tada ispišemo vrijednost log_dir svojstvo kada naša klasa ispitivanja završi:

@AfterClass javna statička void tearDownAfterClass () baca iznimku {System.out.println (System.getProperty ("log_dir")); } 

Vidimo da je vrijednost imovine vraćena na izvornu vrijednost:

/ tmp / baeldung / logs

4.2. Pružanje više svojstava

Ako trebamo pružiti više svojstava, možemo koristiti i metoda za spajanje onoliko vrijednosti svojstava koliko je potrebno za naš test:

@Rule javni konačni ProvideSystemProperty providesSystemPropertyRule = new ProvideSystemProperty ("log_dir", "test / resources"). I ("another_property", "another_value")

4.3. Pružanje svojstava iz datoteke

Isto tako, također imamo mogućnost pružanja svojstava iz datoteke ili resursa staze za klase pomoću ProvideSystemProperty Pravilo:

@Rule javni konačni ProvideSystemProperty providesSystemPropertyFromFileRule = ProvideSystemProperty.fromResource ("/ test.properties"); @Test javna praznina givenProvideSystemPropertyFromFile_whenGetName_thenNameIsProvidedSuccessfully () {assertEquals ("treba navesti ime", "baeldung", System.getProperty ("name")); assertEquals ("treba navesti verziju", "1.0", System.getProperty ("verzija")); }

U gornjem primjeru pretpostavljamo da imamo a test.svojstva datoteka na putu predavanja:

name = baeldung verzija = 1.0

4.4. Pružanje svojstava s JUnit5 i Lambdas

Kao što smo već spomenuli, mogli bismo koristiti i System Lambda verziju knjižnice za provedbu testova kompatibilnih s JUnit5.

Pogledajmo kako implementirati naš test pomoću ove verzije knjižnice:

@BeforeAll static void setUpBeforeClass () baca izuzetak {System.setProperty ("log_dir", "/ tmp / baeldung / logs"); } @Test void givenSetSystemProperty_whenGetLogDir_thenLogDirIsProvidedSuccessfully () baca izuzetak {restoreSystemProperties (() -> {System.setProperty ("log_dir", "test / resources"); assertEquals ("log_dirget test.doc. ("log_dir"));}); assertEquals ("log_dir treba navesti", "/ tmp / baeldung / logs", System.getProperty ("log_dir")); }

U ovoj verziji možemo koristiti restoreSystemProperties metoda za izvršavanje zadane izjave. Unutar ove izjave možemo postaviti i pružiti vrijednosti potrebne za svojstva našeg sustava. Kao što možemo vidjeti nakon što ova metoda završi izvršenje, vrijednost log_dir je isto kao i prije / tmp / baeldung / logs.

Nažalost, nema ugrađene podrške za pružanje svojstava iz datoteka pomoću restoreSystemProperties metoda.

5. Brisanje svojstava sustava

Ponekad bismo možda htjeli obrisati skup svojstava sustava kad naš test započne i vratiti njegove izvorne vrijednosti kad test završi, bez obzira na to prolazi li ili ne.

Možemo koristiti ClearSystemProperties pravilo u tu svrhu:

@Rule javno konačno ClearSystemProperties userNameIsClearedRule = novo ClearSystemProperties ("user.name"); @Test javna praznina givenClearUsernameProperty_whenGetUserName_thenNull () {assertNull (System.getProperty ("user.name")); }

Svojstvo sustava Korisničko ime je jedno od unaprijed definiranih svojstava sustava, koje sadrži ime korisničkog računa. Kao što se i očekivalo u gore navedenom jediničnom testu, uklanjamo ovo svojstvo i provjeravamo je li prazno iz našeg testa.

Povoljno, također možemo proslijediti više naziva svojstava na ClearSystemProperties konstruktor.

6. Ruganje System.in

Povremeno bismo mogli stvoriti interaktivne aplikacije naredbenog retka iz kojih se čita System.in.

Za ovaj ćemo odjeljak upotrijebiti vrlo jednostavan primjer koji čita ime i prezime sa standardnog unosa i spaja ih zajedno:

private String getFullname () {try (Scanner scanner = novi Scanner (System.in)) {String firstName = scanner.next (); String prezime = scanner.next (); return String.join ("", firstName, prezime); }}

Pravila sustava sadrže TextFromStandardInputStream pravilo kojim možemo odrediti linije koje bi trebale biti osigurane prilikom pozivanja System.in:

@Rule javni konačni TextFromStandardInputStream systemInMock = emptyStandardInputStream (); @Test javna praznina givenTwoNames_whenSystemInMock_thenNamesJoinedTogether () {systemInMock.provideLines ("Jonathan", "Cook"); assertEquals ("Imena treba spojiti", "Jonathan Cook", getFullname ()); }

To postižemo korištenjem pružaLine metoda koja uzima parametar varargs kako bi omogućila specificiranje više od jedne vrijednosti.

U ovom primjeru pružamo dvije vrijednosti prije pozivanja getFullname metoda, gdje System.in je referenciran. Naše dvije navedene vrijednosti crte vratit će se svaki put kad nazovemo scanner.next ().

Pogledajmo kako to možemo postići u verziji testa JUnit 5 pomoću System Lambda:

@Test void givenTwoNames_whenSystemInMock_thenNamesJoinedTogether () baca izuzetak {withTextFromSystemIn ("Jonathan", "Cook"). Execute (() -> {assertEquals ("Imena treba ujediniti", "Jonathan Cook", get} Full) ()); }

U ovoj varijaciji koristimo slično nazvane withTextFromSystemIn metoda koja nam omogućuje da odredimo pruženi System.in vrijednosti.

U oba slučaja važno je napomenuti da je nakon završetka testa izvorna vrijednost System.in bit će obnovljena.

7. Ispitivanje System.out i System.err

U prethodnom uputstvu vidjeli smo kako koristiti sistemska pravila za jedinstveno testiranje System.out.println ().

Prikladno, možemo primijeniti gotovo identičan pristup za testiranje koda koji komunicira sa standardnim tokom pogrešaka. Ovaj put koristimo SystemErrRule:

@Rule javni konačni SystemErrRule systemErrRule = novi SystemErrRule (). EnableLog (); @Test javna praznina givenSystemErrRule_whenInvokePrintln_thenLogSuccess () {printError ("Došlo je do pogreške Baeldung Readers !!"); Assert.assertEquals ("Dogodila se pogreška Baeldung Readers !!", systemErrRule.getLog (). Trim ()); } private void printError (izlaz niza) {System.err.println (izlaz); }

Lijepo! Koristiti SystemErrRule, možemo presresti zapise u System.err. Prvo započinjemo bilježenje svega napisanog System.err pozivom na enableLog metoda po našem pravilu. Tada jednostavno zovemo getLog kako bi tekst napisao na System.err otkad smo nazvali enableLog.

Sada, implementiramo JUnit5 verziju našeg testa:

@Test void givenTapSystemErr_whenInvokePrintln_thenOutputIsReturnedSuccessfully () baca iznimku {String text = tapSystemErr (() -> {printError ("Došlo je do pogreške Baeldung Readers !!");}); Assert.assertEquals ("Došlo je do pogreške Baeldung Readers !!", text.trim ()); }

U ovoj verziji, koristimo tapSystemErr metoda koja izvršava izjavu i omogućuje nam hvatanje sadržaja proslijeđenog System.err.

8. Rukovanje System.exit

Aplikacije naredbenog retka obično se završavaju pozivima System.exit. Ako želimo testirati takvu aplikaciju, vjerojatno će se naš test abnormalno završiti prije nego što se završi kad naiđe na kôd koji poziva System.exit.

Srećom, System Rules pružaju lijepo rješenje za rješavanje problema pomoću ExpectedSystemExit Pravilo:

@Rule javni konačni ExpectedSystemExit exitRule = ExpectedSystemExit.none (); @Test javna praznina givenSystemExitRule_whenAppCallsSystemExit_thenExitRuleWorkssAsExpected () {exitRule.expectSystemExitWithStatus (1); Izlaz(); } privatni void izlaz () {System.exit (1); }

Koristiti ExpectedSystemExit pravilo nam omogućuje da iz našeg testa odredimo očekivano System.exit () poziv. U ovom jednostavnom primjeru također provjeravamo očekivani statusni kod pomoću očekujteSystemExitWithStatus metoda.

Nešto slično možemo postići u našoj verziji JUnit 5 pomoću catchSystemExit metoda:

@Test void givenCatchSystemExit_whenAppCallsSystemExit_thenStatusIsReturnedSuccessfully () baca izuzetak {int statusCode = catchSystemExit (() -> {exit ();}); assertEquals ("statusni kôd treba biti 1:", 1, statusCode); }

9. Zaključak

Da rezimiramo, u ovom uputstvu detaljno smo istražili biblioteku sistemskih pravila.

Prvo smo započeli objašnjavajući kako testirati kod koji koristi svojstva sustava. Zatim smo pogledali kako testirati standardni izlaz i standardni ulaz. Na kraju smo pogledali kako postupati s kodom koji poziva System.exit iz naših testova.

Knjižnica sistemskih pravila također pruža podršku za pružanje varijabli okruženja i posebne sigurnosne jasle iz naših testova. Pojedinosti potražite u kompletnoj dokumentaciji.

Kao i uvijek, puni izvorni kôd članka dostupan je na GitHub-u.


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