זמן מערכת עקיפה לבדיקה בג'אווה

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

במדריך מהיר זה נתמקד דרכים שונות לעקוף את זמן המערכת לבדיקה.

לפעמים יש היגיון סביב התאריך הנוכחי בקוד שלנו. אולי כמה שיחות פונקציה כגון תאריך חדש() אוֹ Calendar.getInstance (), שבסופו של דבר הולכים להתקשר System.CurrentTimeMillis.

להקדמה לשימוש ב- שעון ג'אווהאנא עיין במאמר זה כאן. או, לשימוש ב- AspectJ, כאן.

2. שימוש ב- Clock in java.time

ה java.time חבילה ב ג'אווה 8 כולל מעמד מופשט java.time.Clock במטרה לאפשר לחבר שעונים חלופיים לפי הצורך. בכך נוכל לחבר את היישום שלנו או למצוא יישום שכבר מיועד לספק את צרכינו.

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

הראשון הוא תוקן. מזה, אנחנו יכולים להשיג א שָׁעוֹן שתמיד מחזיר אותו דבר רֶגַע, להבטיח שהמבחנים אינם תלויים בשעון הנוכחי.

כדי להשתמש בו, אנו זקוקים ל- רֶגַע ו ZoneOffset:

Instant.now (Clock.fixed (Instant.parse ("2018-08-22T10: 00: 00Z"), ZoneOffset.UTC))

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

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

שעון constantClock = Clock.fixed (ofEpochMilli (0), ZoneId.systemDefault ()); // עבור אל העתיד: שעון שעון = Clock.offset (constantClock, Duration.ofSeconds (10)); // אחורה אחורה עם ערך שלילי: שעון = Clock.offset (constantClock, Duration.ofSeconds (-5)); // משך 0 חוזר לאותו שעון: שעון = Clock.offset (constClock, Duration.ZERO);

עם ה מֶשֶׁך בכיתה, אפשר לתפעל מננו-שניות לימים. כמו כן, אנו יכולים לשלול משך, כלומר לקבל עותק של משך זה עם אורך שלילה.

3. שימוש בתכנות מונחה-היבט

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

כמו כן, ניתן לשזור את שיעורי היישומים כדי להפנות מחדש את השיחה System.currentTimeMillis () או ל תאריך חדש() למחלקת שירות אחרת משלנו.

אחת הדרכים ליישם זאת היא באמצעות AspectJ:

היבט ציבורי ChangeCallsToCurrentTimeInMillisMethod {long around (): call (public static native long java.lang.System.currentTimeMillis ()) && within (user.code.base.pckg. *) {return 0; }} 

בדוגמה שלעיל, אנחנו תופסים כל שיחה ל System.currentTimeMillis() בתוך חבילה שצוינה, שבמקרה זה הוא user.code.base.pckg. *, ומחזירים אפס בכל פעם שאירוע זה קורה.

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

יתרון אחד בשימוש ב- AspectJ הוא בכך שהוא פועל ישירות ברמת קוד הקוד, כך שהוא לא זקוק לקוד המקור המקורי כדי לעבוד.

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

4. ללעוג ל Instant.now () שיטה

אנחנו יכולים להשתמש ב- רֶגַע בכיתה לייצג נקודה מיידית על ציר הזמן. בדרך כלל אנו יכולים להשתמש בו כדי להקליט חותמות זמן לאירועים ביישום שלנו. ה עַכשָׁיו() השיטה של ​​מחלקה זו מאפשרת לנו להשיג את הרגע הנוכחי משעון המערכת באזור הזמן של UTC.

בואו נראה כמה חלופות לשינוי התנהגותה כשאנחנו בודקים.

4.1. עומס יתר עַכשָׁיו() עם שָׁעוֹן

אנחנו יכולים להעמיס על עַכשָׁיו() שיטה עם קבוע שָׁעוֹן למשל. רבים מהשיעורים בבית הספר java.time חבילה יש עַכשָׁיו() שיטה שלוקחת א שָׁעוֹן פָּרָמֶטֶר, מה שהופך את זה לגישה המועדפת עלינו:

@Test הציבור בטל givenFixedClock_whenNow_thenGetFixedInstant () {String instantExpected = "2014-12-22T10: 15: 30Z"; שעון שעון = Clock.fixed (Instant.parse (instantExpected), ZoneId.of ("UTC")); מיידי מיידי = Instant.now (שעון); assertThat (instant.toString ()). isEqualTo (instantExpected); }

4.2. באמצעות PowerMock

בנוסף, אם עלינו לשנות את התנהגות ה- עַכשָׁיו() ללא שליחת פרמטרים, אנו יכולים להשתמש PowerMock:

@RunWith (PowerMockRunner.class) @PrepareForTest ({Instant.class}) בכיתה ציבורית InstantUnitTest {@Test public void givenInstantMock_whenNow_thenGetFixedInstant () {String instantExpected = "2014-12-22T10: 15: 30Z"; שעון שעון = Clock.fixed (Instant.parse (instantExpected), ZoneId.of ("UTC")); מיידי מיידי = Instant.now (שעון); mockStatic (Instant.class); מתי (Instant.now ()). ואז Return (מיידי); מיידי עכשיו = Instant.now (); assertThat (now.toString ()). isEqualTo (instantExpected); }}

4.3. באמצעות JMockit

לחלופין, אנו יכולים להשתמש ב- JMockit סִפְרִיָה.

JMockit מציע לנו שתי דרכים ללעוג לשיטה סטטית. האחד משתמש ב- ללעוג מעמד:

@Test הציבור בטל givenInstantWithJMock_whenNow_thenGetFixedInstant () {String instantExpected = "2014-12-21T10: 15: 30Z"; שעון שעון = Clock.fixed (Instant.parse (instantExpected), ZoneId.of ("UTC")); MockUp חדש () {@Mock מיידי ציבורי עכשיו () {להחזיר Instant.now (שעון); }}; מיידי עכשיו = Instant.now (); assertThat (now.toString ()). isEqualTo (instantExpected); }

והשני משתמש ב- ציפיות מעמד:

@Test הציבור בטל givenInstantWithExpectations_whenNow_thenGetFixedInstant () {שעון שעון = Clock.fixed (Instant.parse ("2014-12-23T10: 15: 30.00Z"), ZoneId.of ("UTC")); Instant instantExpected = Instant.now (שעון); ציפיות חדשות (Instant.class) {{Instant.now (); תוצאה = מיידי צפוי; }}; מיידי עכשיו = Instant.now (); assertThat (now) .isEqualTo (instantExpected); }

5. ללעוג ל LocalDateTime.now () שיטה

עוד שיעור שימושי ב java.time החבילה היא LocalDateTime מעמד. מחלקה זו מייצגת זמן תאריך ללא אזור זמן במערכת לוח השנה ISO-8601. ה עַכשָׁיו() השיטה של ​​מחלקה זו מאפשרת לנו לקבל את תאריך השעה הנוכחי משעון המערכת באזור הזמן המוגדר כברירת מחדל.

אנו יכולים להשתמש באותן חלופות ללעוג לו כפי שראינו קודם. למשל, עומס יתר עַכשָׁיו() עם קבוע שָׁעוֹן:

@Test ציבורי בטל givenFixedClock_whenNow_thenGetFixedLocalDateTime () {שעון שעון = Clock.fixed (Instant.parse ("2014-12-22T10: 15: 30.00Z"), ZoneId.of ("UTC")); מחרוזת dateTimeExpected = "2014-12-22T10: 15: 30"; LocalDateTime dateTime = LocalDateTime.now (שעון); assertThat (dateTime) .isEqualTo (dateTimeExpected); }

6. מסקנה

במאמר זה בחנו דרכים שונות לעקוף את זמן המערכת לבדיקה. ראשית, הסתכלנו על החבילה המקורית java.time וזה שלה שָׁעוֹן מעמד. לאחר מכן ראינו כיצד ליישם היבט לארוג את מערכת מעמד. לבסוף, ראינו חלופות שונות ללעוג ל עַכשָׁיו() שיטה ב רֶגַע ו LocalDateTime שיעורים.

כמו תמיד, ניתן למצוא דוגמאות קוד ב- GitHub.

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