מבוא ל- DBUnit

1. הקדמה

במדריך זה, נסתכל על DBUnit, כלי לבדיקת יחידה שהיה רגיל מִבְחָןאינטראקציות בסיסי נתונים יחסי ב ג'אווה.

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

2. תלות

ראשית, אנו יכולים להוסיף DBUnit לפרויקט שלנו מ Maven Central על ידי הוספת ה- dbunit תלות שלנו pom.xml:

 מבחן org.dbunit dbunit 2.7.0 

אנו יכולים לחפש את הגרסה האחרונה ב- Maven Central.

3. דוגמה שלום לעולם

לאחר מכן, בואו נגדיר א סכימת מסד נתונים:

schema.sql:

צור טבלה אם לא קיים לקוחות (`id` int AUTO_INCREMENT NOT NULL,` first_name` varchar (100) NOT NULL, `last_name` varchar (100) NOT NULL, PRIMARY KEY (` id ')); צור טבלה אם לא קיים פריטים ('id` int AUTO_INCREMENT NOT NULL, `title` varchar (100) NOT NULL,' produced 'date,' price 'float, PRIMARY KEY (' id ')); 

3.1. הגדרת תוכן מסד הנתונים הראשוני

DBUnit מאפשר לנו להגדיר ולהעלות את מערך הבדיקה שלנו בפשטותדרך הצהרתית.

אנו מגדירים כל שורה בטבלה עם אלמנט XML אחד, כאשר שם התג הוא שם טבלה, ושמות התכונות והערכים ממפים לשמות וערכי העמודות בהתאמה. ניתן ליצור את נתוני השורות למספר טבלאות. עלינו ליישם את getDataSet () שיטה של DataSourceBasedDBTestCase להגדרת מערך הנתונים הראשוני, היכן נוכל להשתמש ב- FlatXmlDataSetBuilder להתייחסות לקובץ ה- XML ​​שלנו:

data.xml:

3.2. אתחול חיבור ומסד הנתונים

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

עלינו להאריך את DataSourceBasedDBTestCase למחלקה לאתחל את סכימת מסד הנתונים שלה getDataSource () שיטה:

DataSourceDBUnitTest.java:

מחלקה ציבורית DataSourceDBUnitTest מרחיב את DataSourceBasedDBTestCase {@Override DataSource המוגן getDataSource () {JdbcDataSource dataSource = חדש JdbcDataSource (); dataSource.setURL ("jdbc: h2: mem: ברירת מחדל; DB_CLOSE_DELAY = -1; init = runcript מ- 'classpath: schema.sql'"); dataSource.setUser ("sa"); dataSource.setPassword ("sa"); להחזיר dataSource; } @ DataSet מוגן @Override getDataSet () זורק חריג {להחזיר FlatXmlDataSetBuilder חדש (). Build (getClass (). GetClassLoader () .getResourceAsStream ("data.xml")); }}

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

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

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

@Override מוגן DatabaseOperation getSetUpOperation () {להחזיר DatabaseOperation.REFRESH; } @Override מוגן DatabaseOperation getTearDownOperation () {להחזיר DatabaseOperation.DELETE_ALL; }

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

3.3. השוואת המדינה הצפויה והמדינה בפועל

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

@Test ציבורי בטל givenDataSetEmptySchema_whenDataSetCreated_thenTablesAreEqual () זורק חריג {IDataSet expectDataSet = getDataSet (); ITable expectTable = expectDataSet.getTable ("CLIENTS"); IDataSet databaseDataSet = getConnection (). CreateDataSet (); ITable actualTable = databaseDataSet.getTable ("CLIENTS"); assertEquals (expectTable, actualTable); }

4. צלילה עמוקה לתוך קביעות

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

4.1. טוען בעזרת שאילתת SQL

דרך פשוטה לבדוק את המצב בפועל היא באמצעות שאילתת SQL.

בדוגמה זו נכניס רשומה חדשה לטבלת הלקוחות ואז נאמת את תוכן השורה החדשה שנוצרה. הגדרנו את התפוקה הצפויה ב- קובץ XML נפרדוחילץ את ערך השורה בפועל על ידי שאילתת SQL:

@Test ציבורי בטל givenDataSet_whenInsert_thenTableHasNewClient () זורק חריג {נסה (InputStream הוא = getClass (). GetClassLoader (). GetResourceAsStream ("dbunit / expected-user.xml")) {IDataSet expectDataSet = חדש FlatXmlData.) ITable expectTable = expectDataSet.getTable ("CLIENTS"); חיבור conn = getDataSource (). GetConnection (); conn.createStatement () .executeUpdate ("הכנס ללקוחות (שם ראשון, שם משפחה) ערכים ('ג'ון', 'יאנסן')"); ITable actualData = getConnection () .createQueryTable ("result_name", "SELECT * FROM CLIENTS WHERE last_name =" Jansen ""); assertEqualsIgnoreCols (expectTable, actualData, מחרוזת חדשה [] {"id"}); }}

ה getConnection () שיטת ה- DBTestCase מחלקת קדמון מחזירה ייצוג ספציפי ל- DBUnit של חיבור מקור הנתונים ( IDatabaseConnection למשל). ה createQueryTable () שיטת ה- IDatabaseConnection ניתן להשתמש כדי להביא נתונים בפועל ממסד הנתונים, לשם השוואה עם מצב מסד הנתונים הצפוי, באמצעות Assertion.assertEquals () שיטה. שאילתת SQL הועברה createQueryTable () היא השאילתה שאנחנו רוצים לבדוק. זה מחזיר א שולחן מקרה שאנו משתמשים בו כדי לטעון.

4.2. התעלמות מעמודות

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

נוכל לעשות זאת על ידי השמטת העמודות מסעיפי SELECT בשאילתות SQL, אך DBUnit מספק כלי עזר נוח יותר להשגת זה. בשיטות הסטטיות של DefaultColumnFilter בכיתה נוכל ליצור חדש ITable מופע מקיים על ידי אי הכללת חלק מהעמודות, כפי שמוצג כאן:

@ מבחן בטל פומבי givenDataSet_whenInsert_thenGetResultsAreStillEqualIfIgnoringColumnsWithDifferentProduced () זורק חריג {חיבור חיבור = tester.getConnection (). GetConnection (); מחרוזת [] exclatedColumn = {"id", "produced"}; נסה (InputStream הוא = getClass (). getClassLoader () .getResourceAsStream ("dbunit / expected-ignoring-registered_at.xml")) {IDataSet expectDataSet = FlatXmlDataSetBuilder חדש (). build (is); ITable expectTable = exclatedColumnTable (expectDataSet.getTable ("ITEMS"), exclatedColumn); connection.createStatement () .executeUpdate ("הכנס לפריטים (כותרת, מחיר, הופק) ערכים ('שרשרת', 199.99, עכשיו ())"); IDataSet databaseDataSet = tester.getConnection (). CreateDataSet (); ITable actualTable = exclatedColumnTable (databaseDataSet.getTable ("ITEMS"), ExcludeColumn); assertEquals (TableTable, actualTable); }}

4.3. חקירת כשלים מרובים

אם DBUnit מוצא ערך שגוי, ואז הוא זורק מיד קביעה שגיאה.

במקרים ספציפיים, אנו יכולים להשתמש ב- DiffCollectingFailureHandler בכיתה, שאותה נוכל להעביר ל- Assertion.assertEquals () שיטה כטיעון שלישי.

מטפל בכישלון זה יאסוף את כל הכשלים במקום לעצור על הראשון, כלומר ה Assertion.assertEquals () השיטה תמיד תצליח אם נשתמש ב- DiffCollectingFailureHandler. לכן נצטרך לבדוק באופן פרוגרמטי אם המטפל מצא שגיאות:

@Test ציבורי בטל givenDataSet_whenInsertUnexpectedData_thenFailOnAllUnexpectedValues ​​() זורק חריג {נסה (InputStream הוא = getClass (). GetClassLoader (). GetResourceAsStream ("dbunit / צפוי-מרובה-כישלונות. XmlSetData =) = מזהה (DataSata =) = מזהה (Flatata =). ); ITable expectTable = expectDataSet.getTable ("ITEMS"); חיבור conn = getDataSource (). GetConnection (); DiffCollectingFailureHandler CollectHandler = DiffCollectingFailureHandler חדש (); conn.createStatement () .executeUpdate ("הכנס לפריטים (כותרת, מחיר) ערכים ('סוללה', '1000000')"); ITable actualData = getConnection (). CreateDataSet (). GetTable ("ITEMS"); assertEquals (expectTable, actualData, collectionHandler); if (! collectionHandler.getDiffList (). isEmpty ()) {String message = (String) collectHandler.getDiffList () .stream () .map (d -> formatDifference ((Difference) d)) .collect (joining ("\ n ")); logger.error (() -> הודעה); }}} פורמט מחרוזת סטטי פרטי Difference (Difference diff) {מחזיר "ערך צפוי ב-" + diff.getExpectedTable () .getTableMetaData () .getTableName () + "." + diff.getColumnName () + "שורה" + diff.getRowIndex () + ":" + diff.getExpectedValue () + ", אך היה:" + diff.getActualValue (); }

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

לאחר הפעלת הבדיקה אנו מקבלים דוח מעוצב:

java.lang.AssertionError: ערך צפוי ב- ITEMS. מחיר שורה 5: 199.99, אך היה: 1000000.0 ערך צפוי ב- ITEMS. הופק שורה 5: 23.03.2019, אך היה: ערך צפוי null ב- ITEMS. כותרת שורה 5: שרשרת , אך היה: סוללה ב- com.baeldung.dbunit.DataSourceDBUnitTest.givenDataSet_whenInsertUnexpectedData_thenFailOnAllUnexpectedValues ​​(DataSourceDBUnitTest.java:91)

חשוב לשים לב שבשלב זה ציפינו שהמחיר של הפריט החדש יהיה 199.99 אך הוא היה 1000000.0. ואז אנו רואים שתאריך ההפקה יהיה 23-03-2019, אך בסופו של דבר הוא היה ריק. לבסוף, הפריט הצפוי היה שרשרת ובמקום זאת קיבלנו סוללה.

5. מסקנה

במאמר זה ראינו כיצד DBUnit מספק דרך הצהרתית להגדרת נתוני בדיקה ל לבדוק שכבות גישה לנתונים של יישומי Java.

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


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