מדריך לספריית כללי המערכת

1. סקירה כללית

לפעמים כשכותבים בדיקות יחידה, ייתכן שנצטרך לבדוק קוד שמתקשר ישירות עם ה- מערכת מעמד. בדרך כלל ביישומים כגון כלי שורת פקודה שמתקשרים System.exit ישירות או לקרוא טיעונים באמצעות System.in.

במדריך זה, אנו נסתכל על התכונות הנפוצות ביותר של ספרייה חיצונית מסודרת בשם כללי מערכת המספקת סט של כללי JUnit לבדיקת קוד המשתמשת ב מערכת מעמד.

2. תלות Maven

ראשית, בואו נוסיף את התלות בכללי המערכת שלנו pom.xml:

 com.github.stefanbirkner- כללי מערכת 1.19.0 

נוסיף גם תלות במבדה של מערכת שזמינה גם ממייבן סנטרל:

 com.github.stefanbirkner system-lambda 1.1.0 

כפי שכללי המערכת אינם תומכים ישירות JUnit5, הוספנו את התלות האחרונה. זה מספק את שיטות העטיפה של מערכת למבדה לשימוש בבדיקות. קיימת אלטרנטיבה מבוססת הרחבות לזה הנקראת System Stubs.

3. עבודה עם מאפייני מערכת

לסיכום מהיר, פלטפורמת Java משתמשת ב- נכסים התנגד לספק מידע אודות המערכת והתצורה המקומית. אנו יכולים להדפיס בקלות את המאפיינים:

System.getProperties () .forEach ((מפתח, ערך) -> System.out.println (מפתח + ":" + ערך));

כפי שאנו רואים, מאפיינים כוללים מידע כגון המשתמש הנוכחי, הגרסה הנוכחית של זמן הריצה של Java ומפריד בין שם הנתיב לקבצים:

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

אנו יכולים גם להגדיר מאפייני מערכת משלנו באמצעות System.setProperty שיטה. יש לנקוט משנה זהירות בעבודה עם מאפייני מערכת מהבדיקות שלנו, מכיוון שמאפיינים אלה הם JVM-גלובליים.

לדוגמא, אם אנו מגדירים מאפיין מערכת, עלינו לוודא שנחזיר את המאפיין לערכו המקורי לאחר סיום הבדיקה או אם מתרחשת תקלה. לפעמים זה יכול להוביל להתקנה מסורבלת ולקרוע קוד. עם זאת, אם אנו מזניחים זאת, הדבר עלול להוביל לתופעות לוואי בלתי צפויות בבדיקות שלנו.

בחלק הבא נראה כיצד אנו יכולים לספק, לנקות ולוודא שנשחזר את ערכי מאפייני המערכת לאחר השלמת הבדיקות שלנו בצורה תמציתית ופשוטה.

4. מתן מאפייני מערכת

בואו נדמיין שיש לנו מאפיין מערכת log_dir המכיל את המיקום שבו יש לכתוב את יומנינו והיישום שלנו מגדיר מיקום זה כאשר הוא מתחיל:

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

4.1. ספק נכס יחיד

עכשיו בואו ניקח בחשבון שממבחן היחידה שלנו, אנו רוצים לספק ערך אחר. אנו יכולים לעשות זאת באמצעות ה- ספק SystemProperty כְּלָל:

מחלקה ציבורית ProvidesSystemPropertyWithRuleUnitTest {@Rule הציבור הסופי ProvideSystemProperty providesSystemPropertyRule = חדש ProvideSystemProperty ("log_dir", "test / resources"); @Test public void givenProvideSystemProperty_whenGetLogDir_thenLogDirIsProvidedSuccessfully () {assertEquals ("יש לספק" log_dir "," test / resources ", System.getProperty (" log_dir ")); } // הגדרת בדיקת היחידה ממשיכה} 

משתמש ב ספק את מערכת הפרופרטי כלל, אנו יכולים להגדיר ערך שרירותי עבור מאפיין מערכת נתון לשימוש מהבדיקות שלנו. בדוגמה זו, הגדרנו את log_dir רכוש שלנו מבחן / משאבים מדריך, ומבדיקת היחידה שלנו, פשוט טען כי ערך מאפיין הבדיקה סופק בהצלחה.

אם אז נדפיס את הערך של ה- log_dir נכס לאחר סיום שיעור המבחנים שלנו:

@AfterClass חלל סטטי ציבורי tearDownAfterClass () זורק חריג {System.out.println (System.getProperty ("log_dir")); } 

אנו יכולים לראות שערכו של הנכס הוחזר לערכו המקורי:

/ tmp / baeldung / logs

4.2. מתן נכסים מרובים

אם עלינו לספק מספר מאפיינים, נוכל להשתמש ב- ו שיטה לשרשר כמה שיותר ערכי נכסים כנדרש לבדיקה שלנו:

@ כלל סופי ציבורי ProvideSystemProperty providesSystemPropertyRule = חדש ProvideSystemProperty ("log_dir", "test / resources"). ו- ("another_property", "another_value")

4.3. מתן מאפיינים מקובץ

כמו כן, יש לנו גם אפשרות לספק מאפיינים מקובץ או משאב classpath באמצעות ה- ספק את מערכת הפרופרטי כְּלָל:

@ כלל גמר ציבורי ProvideSystemProperty providesSystemPropertyFromFileRule = ProvideSystemProperty.fromResource ("/ test.properties"); @Test public void givenProvideSystemPropertyFromFile_whenGetName_thenNameIsProvidedSuccessfully () {assertEquals ("יש לספק שם", "baeldung", System.getProperty ("שם")); assertEquals ("יש לספק גרסה", "1.0", System.getProperty ("גרסה")); }

בדוגמה שלעיל אנו מניחים שיש לנו a test.properties קובץ בשביל הכיתה:

שם = גירסת baeldung = 1.0

4.4. מתן נכסים עם JUnit5 ו- Lambdas

כפי שהזכרנו בעבר, נוכל להשתמש גם בגרסת ה- System Lambda של הספרייה כדי ליישם בדיקות התואמות ל- JUnit5.

בואו נראה כיצד ליישם את הבדיקה שלנו באמצעות גרסה זו של הספרייה:

@BeforeAll setid ריק ריק SetUpBeforeClass () זורק חריג {System.setProperty ("log_dir", "/ tmp / baeldung / logs"); } @Test בטל givenSetSystemProperty_whenGetLogDir_thenLogDirIsProvidedSuccessfully () זורק Exception {שחזור SystemProperties (() -> {System.setProperty ("log_dir", "test / resources"); assertEquals ("log_dir יש לספק משאבי". ("log_dir"));}); assertEquals ("יש לספק" log_dir "," / tmp / baeldung / logs ", System.getProperty (" log_dir ")); }

בגרסה זו נוכל להשתמש ב- לשחזר SystemProperties שיטה לביצוע הצהרה נתונה. בתוך הצהרה זו, אנו יכולים להגדיר ולספק את הערכים הנדרשים עבור מאפייני המערכת שלנו. כפי שאנו רואים לאחר ששיטה זו מסיימת את הביצוע, הערך של log_dir זהה לקודם / tmp / baeldung / logs.

למרבה הצער, אין תמיכה מובנית לספק מאפיינים מקבצים המשתמשים ב- לשחזר SystemProperties שיטה.

5. ניקוי מאפייני מערכת

לפעמים אולי נרצה לנקות קבוצה של מאפייני מערכת כאשר הבדיקה שלנו מתחילה ולשחזר את הערכים המקוריים שלהם כאשר הבדיקה מסתיימת ללא קשר אם היא עוברת או נכשלת.

אנחנו יכולים להשתמש ב- ClearSystemProperties כלל למטרה זו:

גמר ציבורי @ כלל ClearSystemProperties userNameIsClearedRule = ClearSystemProperties חדש ("user.name"); @Test ציבורי בטל givenClearUsernameProperty_whenGetUserName_thenNull () {assertNull (System.getProperty ("user.name")); }

מאפיין המערכת שם משתמש הוא אחד ממאפייני המערכת המוגדרים מראש, המכיל את שם חשבון המשתמש. כצפוי במבחן היחידה לעיל, אנו מנקים מאפיין זה ובודקים שהוא ריק מהבדיקה שלנו.

באופן נוח, אנו יכולים גם להעביר מספר שמות נכסים אל ה- ClearSystemProperties בַּנַאִי.

6. לעג System.in

מעת לעת, אנו עשויים ליצור יישומי שורת פקודה אינטראקטיביים שקוראים מתוך System.in.

עבור חלק זה, נשתמש בדוגמה פשוטה מאוד הקוראת שם פרטי ושם משפחה מהקלט הסטנדרטי ומשרשרת אותם יחד:

מחרוזת פרטית getFullname () {try (סורק סורק = סורק חדש (System.in)) {String firstName = scanner.next (); שם משפחה מחרוזת = scanner.next (); להחזיר String.join ("", שם פרטי, שם משפחה); }}

כללי המערכת מכילים את TextFromStandardInputStream כלל שבו אנו יכולים להשתמש כדי לציין את הקווים שיש לספק בעת השיחה System.in:

@ כלל גמר ציבורי TextFromStandardInputStream systemInMock = emptyStandardInputStream (); @Test הציבור בטל givenTwoNames_whenSystemInMock_thenNamesJoinedTogether () {systemInMock.provideLines ("ג'ונתן", "קוק"); assertEquals ("יש לשרשר שמות", "ג'ונתן קוק", getFullname ()); }

אנו משיגים זאת באמצעות מספק קווים שיטה, אשר לוקח פרמטר varargs כדי לאפשר ציון יותר מערך אחד.

בדוגמה זו אנו מספקים שני ערכים לפני קריאה ל- getFullname שיטה, היכן System.in מוזכר. שני ערכי השורות המסופקים שלנו יוחזרו בכל פעם שאנחנו מתקשרים scanner.next ().

בואו נסתכל כיצד נוכל להשיג את אותו הדבר בגרסת JUnit 5 של הבדיקה באמצעות מערכת למבדה:

@Test void givenTwoNames_whenSystemInMock_thenNamesJoinedTogether () זורק Exception {withTextFromSystemIn ("Jonathan", "Cook"). Execute (() -> {assertEquals ("צריך לשרשר שמות", "Jonathan Cook", getFullname ());}; }

בווריאציה זו אנו משתמשים בשם זהה withTextFromSystemIn השיטה, המאפשרת לנו לציין את התנאי System.in ערכים.

חשוב להזכיר בשני המקרים כי לאחר סיום המבחן, הערך המקורי של System.in ישוחזר.

7. בדיקות System.out ו System.err

במדריך קודם ראינו כיצד להשתמש בכללי מערכת לבדיקת יחידות System.out.println ().

באופן נוח, אנו יכולים ליישם גישה כמעט זהה לבדיקת קוד המתקשר עם זרם השגיאות הסטנדרטי. הפעם אנו משתמשים ב- SystemErrRule:

@Rule הסופי הציבורי SystemErrRule systemErrRule = SystemErrRule חדש (). EnableLog (); @Test הציבור בטל givenSystemErrRule_whenInvokePrintln_thenLogSuccess () {printError ("אירעה שגיאה קוראי Baeldung !!"); Assert.assertEquals ("אירעה שגיאה בקוראי Baeldung !!", systemErrRule.getLog (). Trim ()); } ריק ריק ריק (פלט מחרוזת) {System.err.println (פלט); }

נֶחְמָד! משתמש ב SystemErrRule, אנו יכולים ליירט את הכותבים ל System.err. ראשית, אנו מתחילים לרשום את כל מה שנכתב System.err על ידי קריאה ל אפשר לוג שיטה על הכלל שלנו. ואז אנחנו פשוט מתקשרים getLog כדי לקבל את הטקסט שנכתב ל- System.err מאז שהתקשרנו אפשר לוג.

עכשיו, בואו נשתמש בגרסת JUnit5 של הבדיקה שלנו:

@Test בטל givenTapSystemErr_whenInvokePrintln_thenOutputIsReturnedSuccessfully () זורק חריג {טקסט מחרוזת = tapSystemErr (() -> {printError ("אירעה שגיאה קוראי Baungung !!");}); Assert.assertEquals ("אירעה שגיאה בקוראי Baeldung !!", text.trim ()); }

בגרסה זו, אנו משתמשים ב- הקש על SystemErr השיטה, שמבצעת את ההצהרה ומאפשרת לנו לתפוס את התוכן שעבר System.err.

8. טיפול System.exit

יישומי שורת פקודה בדרך כלל מסתיימים באמצעות שיחה System.exit. אם אנו רוצים לבדוק יישום כזה, סביר להניח שהבדיקה שלנו תסתיים בצורה לא תקינה לפני שהיא תסתיים כאשר היא נתקלת בקוד המתקשר System.exit.

למרבה המזל, כללי המערכת מספקים פיתרון מסודר לטיפול בזה באמצעות ExpectedSystemExit כְּלָל:

גמר @ כלל ציבורי ExpectedSystemExit exitRule = ExpectedSystemExit.none (); @ מבט ציבורי בטל givenSystemExitRule_whenAppCallsSystemExit_thenExitRuleWorkssAsExpected () {exitRule.expectSystemExitWithStatus (1); יְצִיאָה(); } יציאת חלל פרטית () {System.exit (1); }

משתמש ב ExpectedSystemExit הכלל מאפשר לנו לציין מהבדיקה שלנו את הצפוי System.exit () שִׂיחָה. בדוגמה פשוטה זו, אנו בודקים גם את קוד המצב הצפוי באמצעות ה- expectSystemExitWithStatus שיטה.

אנו יכולים להשיג משהו דומה בגרסת JUnit 5 שלנו באמצעות catchSystemExit שיטה:

@Test בטל givenCatchSystemExit_whenAppCallsSystemExit_thenStatusIsReturnedSuccessfully () זורק חריג {int statusCode = catchSystemExit (() -> {יציאה ();}); assertEquals ("קוד המצב צריך להיות 1:", 1, statusCode); }

9. מסקנה

לסיכום, במדריך זה חקרנו בפירוט את ספריית כללי המערכת.

ראשית, התחלנו בהסבר כיצד לבדוק קוד המשתמש במאפייני מערכת. ואז בדקנו כיצד לבדוק את הפלט הסטנדרטי ואת הקלט הסטנדרטי. לבסוף, בדקנו כיצד לטפל בקוד המתקשר System.exit מהבדיקות שלנו.

ספריית כללי המערכת מספקת תמיכה במתן משתני סביבה ומנהלי אבטחה מיוחדים מהבדיקות שלנו. הקפד לבדוק את התיעוד המלא לפרטים.

כמו תמיד, קוד המקור המלא של המאמר זמין באתר GitHub.


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