Útmutató a Rendszerszabálykönyvtárhoz

1. Áttekintés

Néha egységtesztek írásakor szükség lehet olyan kód tesztelésére, amely közvetlenül kölcsönhatásba lép a Rendszer osztály. Jellemzően olyan alkalmazásokban, mint a parancssori eszközök, amelyek hívnak System.exit vagy közvetlenül olvassa el az argumentumokat System.in.

Ebben az oktatóanyagban megnézzük a Rendszerszabályok nevű, tiszta külső könyvtár leggyakoribb jellemzőit, amely JUnit-szabályokat tartalmaz a kód teszteléséhez, amely a Rendszer osztály.

2. Maven-függőségek

Először tegyük hozzá a Rendszerszabályok függőségét a sajátunkhoz pom.xml:

 com.github.stefanbirkner rendszerszabályok 1.19.0 

Hozzáadjuk a System Lambda függőséget is, amely a Maven Central-nál is elérhető:

 com.github.stefanbirkner system-lambda 1.1.0 

Mivel a Rendszerszabályok nem támogatják közvetlenül JUnit5, hozzáadtuk az utolsó függőséget. Ez biztosítja a System Lambda burkoló módszereket a tesztekben. Van ennek kiterjesztés-alapú alternatívája, az úgynevezett Rendszercsonkok.

3. A rendszer tulajdonságainak kezelése

A gyors összefoglalás érdekében a Java platform a Tulajdonságok objektum információt nyújtani a helyi rendszerről és a konfigurációról. Könnyen kinyomtathatjuk a tulajdonságokat:

System.getProperties () .forEach ((kulcs, érték) -> System.out.println (kulcs + ":" + érték));

Mint láthatjuk, a tulajdonságok olyan információkat tartalmaznak, mint az aktuális felhasználó, a Java futásidejének jelenlegi verziója és a fájl elérési útjának elválasztója:

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

A. Segítségével beállíthatjuk saját rendszer tulajdonságait is System.setProperty módszer. Óvatosan kell eljárni, ha tesztjeinkben a rendszer tulajdonságokkal dolgozunk, mivel ezek a tulajdonságok JVM-globálisak.

Például, ha beállítunk egy rendszer tulajdonságot, akkor biztosítanunk kell, hogy a teszt végeztével vagy meghibásodás esetén visszaállítsuk az eredeti értéket. Ez néha nehézkes beállításhoz vezethet, és lebonthatja a kódot. Ha azonban ezt elhanyagoljuk, az váratlan mellékhatásokhoz vezethet tesztjeink során.

A következő szakaszban megnézzük, hogy miként nyújthatjuk be, tisztíthatjuk meg és biztosíthatjuk a rendszer tulajdonságainak visszaállítását, miután a tesztjeink tömören és egyszerűen befejeződtek.

4. Rendszer tulajdonságainak biztosítása

Képzeljük el, hogy van egy rendszer tulajdonságunk log_dir amely tartalmazza a naplók írásának helyét, és az alkalmazás elindításakor beállítja ezt a helyet:

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

4.1. Biztosítson egyetlen ingatlant

Most vegyük figyelembe, hogy egységtesztünk alapján egy másik értéket szeretnénk megadni. Ezt megtehetjük a ProvideSystemProperty szabály:

public class ProvidesSystemPropertyWithRuleUnitTest {@Rule public final ProvideSystemProperty providesSystemPropertyRule = new ProvideSystemProperty ("log_dir", "test / resources"); @Test public void givenProvideSystemProperty_whenGetLogDir_thenLogDirIsProvidedSuccessfully () {assertEquals ("log_dir kell megadni", "teszt / erőforrások", System.getProperty ("log_dir")); } // az egység teszt meghatározása folytatódik} 

Használni a ProvideSystemProperty szabály szerint tetszőleges értéket állíthatunk be egy adott rendszertulajdonságra a tesztjeink alapján történő felhasználásra. Ebben a példában a log_dir tulajdon a mi teszt / források könyvtárba, és az egység tesztünkből egyszerűen állítsa be, hogy a teszt tulajdonság értékét sikeresen megadták.

Ha ezután kinyomtatjuk a log_dir tulajdonság, amikor teszt osztályunk teljes:

@AfterClass public static void tearDownAfterClass () dobja a Kivételt {System.out.println (System.getProperty ("log_dir")); } 

Láthatjuk, hogy az ingatlan értéke visszaállt az eredeti értékére:

/ tmp / baeldung / logs

4.2. Több tulajdonság biztosítása

Ha több tulajdonságot kell megadnunk, használhatjuk a és módszer annyi tulajdonságérték összekapcsolására, amennyi a tesztünkhöz szükséges:

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

4.3. Tulajdonságok megadása fájlból

Hasonlóképpen lehetőségünk van tulajdonságokat megadni egy fájlból vagy osztályútvonal erőforrásból a ProvideSystemProperty szabály:

@Rule public final ProvideSystemProperty providesSystemPropertyFromFileRule = ProvideSystemProperty.fromResource ("/ test.properties"); @Test public void givenProvideSystemPropertyFromFile_whenGetName_thenNameIsProvidedSuccessfully () {assertEquals ("a nevet meg kell adni", "baeldung", System.getProperty ("név")); assertEquals ("verziót kell megadni", "1.0", System.getProperty ("verzió")); }

A fenti példában feltételezzük, hogy van egy teszt.tulajdonságok fájl az osztályúton:

név = baeldung verzió = 1.0

4.4. Tulajdonságok biztosítása a JUnit5 és a Lambdas használatával

Mint korábban említettük, a könyvtár System Lambda verzióját is felhasználhatjuk a JUnit5-tel kompatibilis tesztek végrehajtására.

Nézzük meg, hogyan lehet végrehajtani tesztünket a könyvtár ezen verziójával:

@BeforeAll static void setUpBeforeClass () dobja a {System.setProperty ("log_dir", "/ tmp / baeldung / logs" kivételt); } @Test void givenSetSystemProperty_whenGetLogDir_thenLogDirIsProvidedSuccessfully () dobja a {Kivétel {restoreSystemProperties (() -> {System.setProperty ("log_dir", "teszt / erőforrások"); assertEquals ("log_dir erőforrásokat kell biztosítani", "test.getProp", "test.getProp", "test.getProp", "test.getProp", "test.getProp", "test.getProp", "test.getProp", "test.getProp", "test.getProp", "test.getProp /" rendszer ("log_dir"));}); assertEquals ("log_dir kell megadni", "/ tmp / baeldung / logs", System.getProperty ("log_dir")); }

Ebben a verzióban használhatjuk a restoreSystemProperties módszer egy adott utasítás végrehajtására. Ebben a nyilatkozatban beállíthatjuk és megadhatjuk a rendszer tulajdonságaihoz szükséges értékeket. Amint láthatjuk, miután ez a módszer befejezte a végrehajtást, a log_dir ugyanaz, mint korábban / tmp / baeldung / logs.

Sajnos nincs beépített támogatás a tulajdonságokat fájlokból a restoreSystemProperties módszer.

5. A rendszer tulajdonságainak törlése

Előfordulhat, hogy a teszt megkezdésekor törölni szeretnénk a rendszer tulajdonságainak halmazát, és a teszt befejezése után visszaállíthatjuk eredeti értékeiket, függetlenül attól, hogy az sikeres-e vagy sem.

Használhatjuk a ClearSystemProperties szabály erre a célra:

@Rule public final ClearSystemProperties userNameIsClearedRule = új ClearSystemProperties ("felhasználónév"); @Test public void givenClearUsernameProperty_whenGetUserName_thenNull () {assertNull (System.getProperty ("felhasználónév")); }

A rendszer tulajdonság felhasználónév az egyik előre definiált rendszertulajdonság, amely tartalmazza a felhasználói fiók nevét. A fenti egységtesztnek megfelelően, töröljük ezt a tulajdonságot, és ellenőrizzük, hogy üres-e a tesztünkből.

Kényelmesen több tulajdonságnevet is átadhatunk a ClearSystemProperties konstruktőr.

6. Gúnyolódás System.in

Időről időre létrehozhatunk interaktív parancssori alkalmazásokat, amelyekből olvasni lehet System.in.

Ebben a szakaszban egy nagyon egyszerű példát fogunk használni, amely kiolvassa a keresztnevet és a vezetéknevet a szokásos bemenetből, és összefűzi őket:

privát karakterlánc getFullname () {try (Szkenner szkenner = új Szkenner (System.in)) {String keresztnév = szkenner.next (); Karakterlánc vezetéknév = szkenner.next (); return String.join ("", keresztnév, vezetéknév); }}

A Rendszerszabályok tartalmazzák a TextFromStandardInputStream szabály, amellyel megadhatjuk azokat a vonalakat, amelyeket meg kell adni a híváskor System.in:

@Rule public final TextFromStandardInputStream systemInMock = emptyStandardInputStream (); @Test public void givenTwoNames_whenSystemInMock_thenNamesJoinedTogether () {systemInMock.provideLines ("Jonathan", "Cook"); assertEquals ("A neveket összefűzni kell", "Jonathan Cook", getFullname ()); }

Ezt a providesLines metódus, amely egy varargs paramétert vesz igénybe egynél több érték megadásához.

Ebben a példában két értéket adunk meg, mielőtt meghívnánk a getFullname módszer, ahol System.in hivatkozik. A két megadott vonalértékünk minden alkalommal visszaadódik, amikor hívunk scanner.next ().

Vizsgáljuk meg, hogyan érhetjük el ugyanezt a teszt JUnit 5 verziójában a System Lambda segítségével:

@Test void givenTwoNames_whenSystemInMock_thenNamesJoinedTogether () dobja a (z) {Kivételt a withTextFromSystemIn ("Jonathan", "Cook"). Végrehajtás (() -> {assertEquals ("A neveket összefűzni kell", "Jonathan Cook", getFullname ())}; }

Ebben a variációban a hasonló nevűeket használjuk withTextFromSystemIn módszer, amely lehetővé teszi számunkra a megadott megadását System.in értékek.

Fontos megemlíteni mindkét esetben, hogy a teszt befejezése után a System.in helyreállítják.

7. Tesztelés System.out és System.err

Egy korábbi oktatóanyagban láttuk, hogyan lehet a rendszerszabályokat használni az egység teszteléséhez System.out.println ().

Kényelmesen majdnem azonos megközelítést alkalmazhatunk a kód tesztelésére, amely kölcsönhatásba lép a szokásos hibasorral. Ezúttal a SystemErrRule:

@Rule public final SystemErrRule systemErrRule = new SystemErrRule (). EnableLog (); @Test public void givenSystemErrRule_whenInvokePrintln_thenLogSuccess () {printError ("Hiba történt a Baeldung olvasóknál !!"); Assert.assertEquals ("Hiba történt a Baeldung olvasóknál !!", systemErrRule.getLog (). Trim ()); } private void printError (karakterlánc kimenet) {System.err.println (output); }

Szép! Használni a SystemErrRule, elfoghatjuk az írásokat System.err. Először elkezdünk naplózni mindent, amire írtunk System.err felhívásával a enableLog módszer a szabályunkon. Akkor egyszerűen hívunk getLog hogy a szöveget a System.err-be írjuk, mióta hívtuk enableLog.

Most hajtsuk végre tesztünk JUnit5 verzióját:

@Test void givenTapSystemErr_whenInvokePrintln_thenOutputIsReturnedSuccessfully () dobja a Kivételt {String text = tapSystemErr (() -> {printError ("Hiba történt Baeldung Readers !!");}); Assert.assertEquals ("Hiba történt a Baeldung Readers !!", text.trim ()); }

Ebben a verzióban felhasználjuk a csapSystemErr metódus, amely végrehajtja az utasítást, és lehetővé teszi a továbbított tartalom rögzítését System.err.

8. Kezelés System.exit

A parancssori alkalmazások általában hívással zárulnak le System.exit. Ha tesztelni szeretnénk egy ilyen alkalmazást, akkor valószínűleg tesztünk rendellenesen leáll, mielőtt befejezné, amikor találkozik a hívó kóddal System.exit.

Szerencsére a Rendszerszabályok elegáns megoldást kínálnak ennek kezelésére a ExpectedSystemExit szabály:

@Rule public final ExpectedSystemExit exitRule = ExpectedSystemExit.none (); @Test public void givenSystemExitRule_whenAppCallsSystemExit_thenExitRuleWorkssAsExpected () {exitRule.expectSystemExitWithStatus (1); kijárat(); } private void exit () {System.exit (1); }

Használni a ExpectedSystemExit szabály lehetővé teszi számunkra, hogy tesztünkből meghatározzuk a várható értéket System.exit () hívás. Ebben az egyszerű példában a várható állapotkódot is ellenőrizzük a VárjSystemExitWithStatus módszer.

Valami hasonlót érhetünk el a JUnit 5 verziónkban a catchSystemExit módszer:

@Test void givenCatchSystemExit_whenAppCallsSystemExit_thenStatusIsReturnedSuccessfully () dobja az {int statusCode = catchSystemExit (() -> {exit ();}) kivételet; assertEquals ("az állapotkód legyen 1:", 1, statusCode); }

9. Következtetés

Összefoglalva, ebben az oktatóanyagban részletesen feltártuk a Rendszerszabályok könyvtárat.

Először azzal kezdtük, hogy elmagyarázzuk a rendszer tulajdonságait használó kód tesztelését. Ezután megvizsgáltuk, hogyan teszteljük a standard kimenetet és a standard bemenetet. Végül megvizsgáltuk, hogyan kezeljük a hívó kódokat System.exit tesztjeinkből.

A System Rules könyvtár támogatást nyújt környezeti változók és speciális biztonsági szempontok biztosításához is tesztjeinkből. A részletekről feltétlenül nézze meg a teljes dokumentációt.

Mint mindig, a cikk teljes forráskódja elérhető a GitHubon.