בדיקת זרמים ריאקטיביים באמצעות StepVerifier ו- TestPublisher

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

במדריך זה נבחן מקרוב את בדיקת הזרמים התגובתיים עם StepVerifier ו TestPublisher.

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

2. תלות Maven

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

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

 io.project reactor reactor test test 3.2.3.RELEASE 

3. StepVerifier

בכללי, מבחן כור יש שני שימושים עיקריים:

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

המקרה הנפוץ ביותר בבדיקת זרמים תגובתי הוא כאשר יש לנו מפרסם (א שֶׁטֶף אוֹ מונו) המוגדר בקוד שלנו. אנחנו רוצים לדעת איך זה מתנהג כשמישהו מנוי.

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

קודם כל, בואו ניצור מו"ל עם כמה מפעילים.

נשתמש ב- Flux.just (אלמנטים T). שיטה זו תיצור שֶׁטֶף שפולט אלמנטים נתונים ואז משלים.

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

מקור שטף = Flux.just ("ג'ון", "מוניקה", "מארק", "קלואה", "פרנק", "קספר", "אוליביה", "אמילי", "קייט"). פילטר (שם -> שם .length () == 4) .map (מחרוזת :: toUpperCase);

3.1. תרחיש שלב אחר שלב

עכשיו, בואו נבדוק את שלנו מָקוֹר עם StepVerifier על מנת לבדוק מה יקרה כאשר מישהו יצטרף כמנוי:

StepVerifier .create (source) .expectNext ("JOHN") .expectNextMatches (name -> name.startsWith ("MA")) .expectNext ("CLOE", "CATE") .expectComplete () .verify ();

ראשית, אנו יוצרים a StepVerifier בונה עם לִיצוֹר שיטה.

לאחר מכן, אנו עוטפים את שלנו שֶׁטֶף מקור שנמצא בבדיקה. האות הראשון מאומת באמצעות expectNext (אלמנט T), אבל באמת, אנו יכולים להעביר מספר כלשהו של אלמנטים אל מצפה הבא.

אנחנו יכולים גם להשתמש expectNextMatches ולספק א לְבַסֵס להתאמה אישית יותר.

לציפייה האחרונה שלנו, אנו מצפים שהזרם שלנו יושלם.

ולבסוף, אנו משתמשים תאשר() להפעיל את המבחן שלנו.

3.2. חריגים ב StepVerifier

עכשיו, בואו נשרשר את שלנו שֶׁטֶף מו"ל עם מונו.

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

שגיאת שטף = source.concatWith (Mono.error (IllegalArgumentException חדש ("המסר שלנו")));

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

StepVerifier .create (error) .expectNextCount (4) .expectErrorMatches (לזרוק -> מופע זורק של IllegalArgumentException && throwable.getMessage (). שווה ("המסר שלנו")). Verify ();

אנו יכולים להשתמש בשיטה אחת בלבד כדי לאמת חריגים. ה OnError אות מודיע למנוי כי המו"ל סגור עם מצב שגיאה. לכן, איננו יכולים להוסיף ציפיות נוספות לאחר מכן.

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

  • expectError () - צפה לכל סוג של שגיאה
  • expectError (מחלקה clazz) – מצפה לשגיאה מסוג מסוים
  • expectErrorMessage (מחרוזת errorMessage) - מצפה לשגיאה בהודעה ספציפית
  • expectErrorMatches (חזוי פרדיקט) - צפה לשגיאה שתואמת את הקבץ הנתון
  • expectErrorSatisfies (הצהרת הצרכן הצרכן) - צורכים א זורק על מנת לבצע קביעה מותאמת אישית

3.3. בדיקת מפרסמים מבוססי זמן

לפעמים המפרסמים שלנו מבוססים על זמן.

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

StepVerifier.withVirtualTime builder נועד למנוע בדיקות ארוכות טווח.

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

כדי להדגים כיצד אנו יכולים לבדוק עיכוב צפוי בין האירועים, בואו ליצור שֶׁטֶף עם מרווח של שנייה אחת שנמשכת שתי שניות. אם הטיימר פועל כראוי, עלינו לקבל רק שני אלמנטים:

StepVerifier .withVirtualTime (() -> Flux.interval (Duration.ofSeconds (1)). Take (2)) .expectSubscription () .expectNoEvent (Duration.ofSeconds (1)) .expectNext (0L). ThenAwait (Duration.ofSeconds (1)) .expectNext (1L) .verifyComplete ();

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

ישנן שתי שיטות ציפייה עיקריות העוסקות בזמן:

  • thenAwait (משך משך הזמן) - מושהה את הערכת השלבים; אירועים חדשים עשויים להתרחש במהלך תקופה זו
  • expectNoEvent (משך משך הזמן) - נכשל כאשר אירוע כלשהו מופיע במהלך מֶשֶׁך; הרצף יעבור עם נתון מֶשֶׁך

שימו לב שהאות הראשון הוא אירוע המנוי, כך כֹּל expectNoEvent (משך משך הזמן) צריך להקדים expectSubscription ().

3.4. טענות לאחר ביצוע עם StepVerifier

לכן, כפי שראינו, פשוט לתאר את הציפיות שלנו שלב אחר שלב.

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

בואו ניצור מו"ל מותאם אישית. זה יפלוט כמה אלמנטים, ואז ישלים, ישהה ​​ויפלט אלמנט אחד נוסף, אותו נפיל:

מקור שטף = Flux.create (emitter -> {emitter.next (1); emitter.next (2); emitter.next (3); emitter.complete (); נסה {Thread.sleep (1000);} לתפוס ( InterruptedException e) {e.printStackTrace ();} emitter.next (4);}). Filter (number -> number% 2 == 0);

אנו מצפים שהיא תנפיק 2, אך תפיל 4, מכיוון שהתקשרנו emitter.complete ראשון.

אז בואו נאמת התנהגות זו באמצעות VerifiedThenAssertThat. שיטה זו חוזרת StepVerifier. הצעות שעליהם נוכל להוסיף את קביעותינו:

@Test ציבורי בטל droppElements () {StepVerifier.create (מקור) .expectNext (2) .expectComplete () .verifyThenAssertThat () .hasDropped (4) .tookLessThan (Duration.ofMillis (1050)); }

4. הפקת נתונים עם TestPublisher

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

למשל, ייתכן שיש לנו מצב מסוים מאוד אותו אנו רוצים לבדוק.

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

בשני המקרים נוכל להשתמש TestPublisher, איזה מאפשר לנו להפעיל תכנותית אותות שונים:

  • הבא (ערך T) אוֹ הבא (ערך T, מנוחה T) - שלח אות אחד או יותר למנויים
  • פולטים (ערך T) - כמו הבא (T) אבל קורא לְהַשְׁלִים() לאחר מכן
  • לְהַשְׁלִים() - מסיים מקור עם ה- לְהַשְׁלִים אוֹת
  • שגיאה (trrowable tr) - מסיים מקור עם שגיאה
  • שטף () - שיטה נוחה לעטוף א TestPublisher לְתוֹך שֶׁטֶף
  • מונו () - אותו אנחנו שֶׁטֶף() אבל עוטף לא מונו

4.1. ליצור TestPublisher

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

TestPublisher .create () .next ("ראשון", "שני", "שלישי"). שגיאה (RuntimeException חדש ("הודעה"));

4.2. TestPublisher בִּפְעוּלָה

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

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

ראשית, בואו ניצור מחלקה שמשתמשת בה שֶׁטֶף כפרמטר הבנאי לביצוע הפעולה getUpperCase ():

class UppercaseConverter {מקור שטף סופי פרטי; UppercaseConverter (מקור שטף) {this.source = source; } שטף getUpperCase () {מקור החזרה .מפה (מחרוזת :: toUpperCase); }}

נניח ש ממיר אותיות רישיות הוא המעמד שלנו עם לוגיקה ומפעילים מורכבים, ואנחנו צריכים לספק נתונים מאוד מסוימים מה- מָקוֹר מוֹצִיא לָאוֹר.

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

סופי TestPublisher testPublisher = TestPublisher.create (); UppercaseConverter uppercaseConverter = UppercaseConverter חדש (testPublisher.flux ()); StepVerifier.create (uppercaseConverter.getUpperCase ()). ואז (() -> testPublisher.emit ("aA", "bb", "ccc")) .expectNext ("AA", "BB", "CCC"). verifyComplete ();

בדוגמה זו, אנו יוצרים מבחן שֶׁטֶף מפרסם ב- ממיר אותיות רישיות פרמטר קונסטרוקטור. ואז, שלנו TestPublisher פולט שלושה אלמנטים ומשלים.

4.3. לא התנהג יפה TestPublisher

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

בואו נסתכל על א TestPublisher שלא יזרוק א NullPointerException בשביל ה ריק אֵלֵמֶנט:

TestPublisher .createNoncompliant (TestPublisher.Violation.ALLOW_NULL) .emit ("1", "2", null, "3"); 

בנוסף ל לאפשר NULL, אנחנו יכולים גם להשתמש TestPublisher. הפרה ל:

  • REQUEST_OVERFLOW - מאפשר להתקשר הַבָּא() בלי לזרוק IllegalStateException כשיש מספר לא מספיק של בקשות
  • CLEANUP_ON_TERMINATE - מאפשר שליחת כל אות סיום מספר פעמים ברציפות
  • DEFER_CANCELLATION - מאפשר לנו להתעלם מאותות ביטול ולהמשיך עם אלמנטים פולטים

5. מסקנה

במאמר זה, דנו בדרכים שונות לבדיקת זרמים תגובתי מה- כור אביב פּרוֹיֶקט.

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

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


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