מבוא ל- EasyMock
1. הקדמה
בעבר דיברנו רבות על JMockit ו- Mockito.
במדריך זה ניתן הקדמה לכלי לעג אחר - EasyMock.
2. תלות Maven
לפני שנצלול פנימה, בואו נוסיף את התלות הבאה שלנו pom.xml:
מבחן org.easymock easymock 3.5.1
הגרסה האחרונה תמיד נמצאת כאן.
3. מושגי ליבה
כאשר מייצרים דמה, אנו יכולים לדמות את אובייקט היעד, לציין את התנהגותו ולבסוף לאמת אם הוא משמש כצפוי.
העבודה עם הלעג של איזימוק כוללת ארבעה שלבים:
- יצירת דמה של מחלקת היעד
- רישום התנהגותה הצפויה, כולל הפעולה, התוצאה, החריגים וכו '.
- שימוש בלעג בבדיקות
- לאמת אם זה מתנהג כצפוי
לאחר סיום ההקלטה שלנו, אנו מעבירים אותו למצב "הפעלה חוזרת", כך שהמדומה תתנהג כפי שהוקלט כאשר אנו משתפים פעולה עם כל אובייקט שישתמש בו.
בסופו של דבר אנו בודקים אם הכל מתנהל כמצופה.
ארבעת השלבים שהוזכרו לעיל מתייחסים לשיטות ב org.easymock.EasyMock:
- לִלְעוֹג(…): מייצר לעג של מחלקת היעד, בין אם זה מחלקה קונקרטית או ממשק. לאחר היצירה, מוק נמצא במצב "הקלטה", כלומר EasyMock יתעד כל פעולה שהאובייקט המדומה יבצע, ויחזיר אותם למצב "הפעלה חוזרת".
- לְצַפּוֹת(…): בשיטה זו נוכל להגדיר ציפיות, כולל שיחות, תוצאות וחריגים, לפעולות הקלטה משויכות
- שידור חוזר(…): מעביר מדומה נתונה למצב "הפעלה חוזרת". ואז, כל פעולה שתפעיל שיחות שיטה שהוקלטו בעבר תשחזר "תוצאות מוקלטות"
- תאשר(…): מאמת כי כל הציפיות נענו וכי שום שיחה לא צפויה בוצעה ללעג
בחלק הבא נראה כיצד פועלים שלבים אלה בפעולה תוך שימוש בדוגמאות בעולם האמיתי.
4. דוגמה מעשית ללעג
לפני שנמשיך, נסתכל על ההקשר לדוגמא: נגיד שיש לנו קורא של הבלוג Baeldung, שאוהב לדפדף בכתבות באתר, ואז הוא / היא מנסה לכתוב מאמרים.
נתחיל ביצירת המודל הבא:
מעמד ציבורי BaeldungReader {Article ArticleReader פרטי; פרטי IArticleWriter articleWriter; // הקבלנים הציבוריים BaeldungArticle readNext () {return articleReader.next (); } רשימת ציבורי readTopic (נושא מחרוזת) {return articleReader.ofTopic (נושא); } כתיבת מחרוזות ציבורית (כותרת מחרוזת, תוכן מחרוזת) {return articleWriter.write (כותרת, תוכן); }}
במודל זה יש לנו שני חברים פרטיים: ה- ArticleReader(כיתת בטון) וה ArticleWriter (ממשק).
לאחר מכן נלעוג עליהם לאמת BaeldungReaderהתנהגות.
5. לעג עם קוד Java
נתחיל ללעוג ל- ArticleReader.
5.1. לגלוג אופייני
אנו מצפים כי articleReader.next () שיטה להיקרא כאשר קורא מדלג על מאמר:
@Test הציבור בטל כאשר ReadNext_thenNextArticleRead () {ArticleReader mockArticleReader = דמה (ArticleReader.class); BaeldungReader baeldungReader = BaeldungReader חדש (mockArticleReader); expect (mockArticleReader.next ()). andReturn (null); שידור חוזר (mockArticleReader); baeldungReader.readNext (); אמת (mockArticleReader); }
בקוד המדגם לעיל, אנו מקפידים על הליך 4 השלבים ולועגים ל ArticleReader מעמד.
אם כי באמת לא אכפת לנו מה mockArticleReader.next () מחזיר, אנחנו עדיין צריכים לציין ערך החזר עבור mockArticleReader.next () על ידי שימוש ב מצפה (...). וחזור (...).
עם לְצַפּוֹת(…), EasyMock מצפה שהשיטה תחזיר ערך או תזרוק יוצא מן הכלל.
אם פשוט נעשה:
mockArticleReader.next (); שידור חוזר (mockArticleReader);
EasyMock תתלונן על כך, מכיוון שהיא דורשת להתקשר מצפה (...). וחזור (...) אם השיטה מחזירה משהו.
אם זה א בָּטֵל שיטה, אנחנו יכולים לְצַפּוֹת הפעולה שלה באמצעות expectLastCall () ככה:
mockArticleReader.someVoidMethod (); expectLastCall (); שידור חוזר (mockArticleReader);
5.2. הזמנה חוזרת
אם אנחנו צריכים שפעולות ישוחזרו לפי סדר מסוים, אנחנו יכולים להיות קפדניים יותר:
@ מבחן ציבורי בטל כאשר ReadNextAndSkimTopics_thenAllAllowed () {ArticleReader mockArticleReader = strictMock (ArticleReader.class); BaeldungReade baeldungReader = BaeldungReader חדש (mockArticleReader); expect (mockArticleReader.next ()). andReturn (null); expect (mockArticleReader.ofTopic ("easymock")). ו- Return (null); שידור חוזר (mockArticleReader); baeldungReader.readNext (); baeldungReader.readTopic ("easymock"); אמת (mockArticleReader); }
בקטע זה אנו להשתמש strictMock (...) כדי לבדוק את סדר שיחות השיטה. ללעג שנוצר על ידי לִלְעוֹג(…) ו strictMock (...), כל שיחות שיטה בלתי צפויות יגרמו ל- קביעה שגיאה.
כדי לאפשר כל קריאת שיטה ללעג, נוכל להשתמש niceMock (...):
@ מבחן ציבורי בטל כאשר ReadNextAndOthers_thenAllowed () {ArticleReader mockArticleReader = niceMock (ArticleReader.class); BaeldungReade baeldungReader = BaeldungReader חדש (mockArticleReader); expect (mockArticleReader.next ()). andReturn (null); שידור חוזר (mockArticleReader); baeldungReader.readNext (); baeldungReader.readTopic ("easymock"); אמת (mockArticleReader); }
כאן לא ציפינו ל baeldungReader.readTopic (...) להיקרא, אבל איזי-מוק לא יתלונן. עם niceMock (...), ל- EasyMock עכשיו אכפת רק אם אובייקט היעד ביצע פעולה צפויה או לא.
5.3. לַעֲגָנִי יוצא מן הכלל זורק
עכשיו, בואו נמשיך ללעוג לממשק IArticleWriter, ואיך להתמודד עם הצפוי זורקים:
@ מבחן ציבורי בטל כאשר WriteMaliciousContent_thenArgumentIllegal () {// ללעג וליזום מצפה (mockArticleWriter .write ("easymock", "")). AndTrow (חדש IllegalArgumentException ()); שידור חוזר (mockArticleWriter); // לכתוב תוכן זדוני וללכוד חריג כצפוי אמת חריג (mockArticleWriter); assertEquals (IllegalArgumentException.class, expectException.getClass ()); }
בקטע הקודם אנו מצפים ש- ArticleWriter הוא איתן מספיק כדי לזהות התקפות XSS (Scripting Cross-site).
לכן כאשר הקורא מנסה להזרים קוד זדוני לתוכן המאמר, הכותב צריך לזרוק IllegalArgumentException. רשמנו התנהגות צפויה זו באמצעות מצפה (...) .andTrow (...).
6. לעג עם ביאור
EasyMock תומך גם בהזרקת לעגים באמצעות הערות. כדי להשתמש בהם, עלינו להריץ את בדיקות היחידות שלנו EasyMockRunner כדי שזה יעבוד @לִלְעוֹג ו @נושא הבדיקה ביאורים.
בוא ונכתוב קטעים קודמים:
@RunWith (EasyMockRunner.class) מעמד ציבורי BaeldungReaderAnnotatedTest {@Mock ArticleReader mockArticleReader; @TestSubject BaeldungReader baeldungReader = BaeldungReader חדש (); @ מבחן פומבי בטל כאשר ReadNext_thenNextArticleRead () {expect (mockArticleReader.next ()). And Return (null); שידור חוזר (mockArticleReader); baeldungReader.readNext (); אמת (mockArticleReader); }}
שווה ערך ל לִלְעוֹג(…), מוזרק דמה לשדות שמסומנים עליהם @לִלְעוֹג. והלעגים האלה יוזרקו לשדות הכיתה שמסומנים עליהם @נושא הבדיקה.
בקטע הקוד שלמעלה לא אתחלנו את ה- ArticleReader שדה ב baeldungReader. כשמתקשרים baeldungReader.readNext (), אנו יכולים לקשר את זה באופן מרומז mockArticleReader.
זה היה בגלל mockArticleReader הוזרק ל המאמר הקורא שדה.
שים לב שאם אנחנו רוצים להשתמש במבחן אחר במקום EasyMockRunnerנוכל להשתמש בכלל הבדיקה JUnit EasyMockRule:
מחלקה ציבורית BaeldungReaderAnnotatedWithRuleTest {@ כלל ציבור EasyMockRule mockRule = EasyMockRule חדש (זה); // ... @Test public void whenReadNext_thenNextArticleRead () {expect (mockArticleReader.next ()). AndReturn (null); שידור חוזר (mockArticleReader); baeldungReader.readNext (); אמת (mockArticleReader); }}
7. לעג עם EasyMockSupport
לפעמים אנחנו צריכים להציג כמה לעגים במבחן אחד, ועלינו לחזור ידנית:
שידור חוזר (A); שידור חוזר (B); שידור חוזר (C); // ... אמת (א); אמת (B); אמת (C);
זה מכוער, ואנחנו זקוקים לפיתרון אלגנטי.
למרבה המזל, יש לנו שיעור EasyMockSupport ב- EasyMock לעזור להתמודד עם זה. זה עוזר לעקוב אחר הלעג, כזה שנוכל להפעיל מחדש ולאמת אותם אצווה כזו:
// ... מחלקה ציבורית BaeldungReaderMockSupportTest מרחיב את EasyMockSupport {// ... @Test public void whenReadAndWriteSequencially_thenWorks () {expect (mockArticleReader.next ()). and Retur (null). times (2). andTrow (new NoSuchElementException) ; מצפה (mockArticleWriter.write ("כותרת", "תוכן")). וחזור ("BAEL-201801"); השב לכולם(); // לבצע פעולות קריאה וכתיבה ברצף VerifiedAll (); assertEquals (NoSuchElementException.class, expectException.getClass ()); assertEquals ("BAEL-201801", ArticleId); }}
כאן לעגנו לשניהם ArticleReader ו ArticleWriter. כאשר הגדרנו את הלעג למצב "הפעלה חוזרת", השתמשנו בשיטה סטטית השב לכולם() המסופק על ידי EasyMockSupport, ומשומש אמת כל () כדי לאמת את התנהגויותיהם באופן קבוע.
הצגנו גם פִּי(…) שיטה ב לְצַפּוֹת שלב. זה עוזר לציין כמה פעמים אנו מצפים לקרוא לשיטה כדי שנוכל להימנע מהכנסת קוד כפול.
אנחנו יכולים גם להשתמש EasyMockSupport באמצעות משלחת:
EasyMockSupport easyMockSupport = EasyMockSupport חדש (); @Test הציבור בטל כאשר ReadAndWriteSequencially_thenWorks () {ArticleReader mockArticleReader = easyMockSupport .createMock (ArticleReader.class); IArticleWriter mockArticleWriter = easyMockSupport .createMock (IArticleWriter.class); BaeldungReader baeldungReader = BaeldungReader חדש (mockArticleReader, mockArticleWriter); expect (mockArticleReader.next ()). andReturn (null); מצפה (mockArticleWriter.write ("כותרת", "תוכן")). וחזור (""); easyMockSupport.replayAll (); baeldungReader.readNext (); baeldungReader.write ("כותרת", "תוכן"); easyMockSupport.verifyAll (); }
בעבר השתמשנו בשיטות או ביאורים סטטיים כדי ליצור ולנהל לעגים. מתחת למכסה המנוע, הלעג הסטטי והמבואר האלה נשלטים על ידי גלובלי EasyMockSupport למשל.
כאן, אנו מיישרים זאת במפורש ולקחת את כל הלעג האלה בשליטתנו, באמצעות משלחת. זה עשוי לסייע במניעת בלבול אם יש התנגשויות בשמות בקוד הבדיקה שלנו עם EasyMock או שיש מקרים דומים.
8. מסקנה
במאמר זה הצגנו בקצרה את השימוש הבסיסי ב- EasyMock, כיצד ליצור אובייקטים מדומים, להקליט ולהתנהל מחדש על התנהגויותיהם, ולוודא אם הם מתנהגים נכון.
אם אתה מעוניין, עיין במאמר זה לצורך השוואה בין EasyMock, Mocket ו- JMockit.
כמו תמיד, ניתן למצוא את היישום המלא ב- Github.