亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

運用 DBUnit 進行高效的單元測試

2019-11-18 13:14:43
字體:
來源:轉載
供稿:網友

  現實系統中通常會有一些具有外部依靠性的對象,這些對象和數據庫或者其他對象存在諸多關聯。假如我們對這樣的對象編寫單元和組件級測試的話,可以想象將是非常麻煩的一件事.因為這種外部依靠性的存在,使的我們很難將對象孤立出來進行測試。經常提及的白盒測試法,基本上就是通過控制對象的外部依靠性來達到隔離對象的目的,使的可以操作這些對象的狀態和相關行為。
  
  運用 模擬對象(mock objects)
  或者stubs,就是一個控制對象外部依靠性的解決方案。通過隔離那些關聯的數據庫訪問類,象JDBC的相關操作類,對于控制對象外部依靠性將是很有效的。但模擬對象的解決方案對一些非凡的應用系統架構就顯得力不從心了,象那些運用了EJB的CMP(container-managed
  persistence)或者 JDO(java Data
  Objects)的應用系統架構,在這些架構里,數據庫的訪問對象是在最底層的而且很隱蔽。
  
  由Manuel Laflamme
  編寫的開放源代碼的DBUnit架構體系,對于控制系統內部的數據庫依靠性提供了一個非常不錯的解決方案。他答應程序員在整個的測試過程中自由的治理控制數據庫的狀態,這很重要。利用DBUnit,在測試之前,我們可以給目標數據庫植入我們需要的數據集,而且,在測試完畢后,數據庫完全能夠回溯到測試前的狀態。
  
  在很多成功的軟件項目中,測試自動化往往是要害的層面。DBUnit答應開發人員創建測試用例代碼,在這些測試用例的生命周期內我們可以很好的控制數據庫的狀態。而且,這些測試用例是很輕易實現自動化的。這樣在測試過程中我們無須對它進行人工的干預,為人工干預造成的后果而擔心就更沒必要了。
  
  簡單介紹
  配置使用DBUnit的第一步我們首先需要知道如何生成數據庫schema,這個文件是xml格式的,其中包括了數據庫的表及相關數據信息。
  
  例如,這里有一個數據庫表employee
  ,我們可以用SQL的形式這樣將他表示出來。
  
  而且,我們可以看到,一個簡單的數據集可以這樣表示
  
  在DBUnit中,上面這個表和抽樣數據信息可以用XML文件的形式這樣表示:
  
  <EMPLOYEE employee_uid='1'
  start_date='2001-11-01'
  first_name='Andrew'
  ssn='xxx-xx-xxxx'
  last_name='Glover' />
  
  這個生成的XML格式的文件可以作為系統所需的所有種子文件(seed
  files)的樣本模版.
  
  為相互關聯的測試場景創建多個種子文件是一個很有效的策略,就象通過不同的數據庫文件來區分隔離數據庫狀態是一個道理。多種子文件策略可以將我們的測試目標鎖定到較小的范圍,目標數據可以只針對數據庫的表,而不是整個數據庫。
  
  為了給目標數據庫植入不同的職員記錄,我們需要的XML數據文件如下所示:
  <?xml version='1.0' encoding='UTF-8'?>
  
  <dataset>
  <EMPLOYEE employee_uid='1'
  start_date='2001-01-01'
  first_name='Drew' ssn='000-29-2030'
  last_name='Smith' />
  
  <EMPLOYEE employee_uid='2'
  start_date='2002-04-04'
  first_name='Nick' ssn='000-90-0000'
  last_name='Marquiss' />
  
  <EMPLOYEE employee_uid='3'
  start_date='2003-06-03'
  first_name='Jose' ssn='000-67-0000'
  last_name='Whitson' />
  </dataset>
  
  現在,要讓DBUnit和我們所需的數據庫schema一起工作了,對于程序員來說,我們使用DBUnit進行測試可以有兩種選擇:通過直接編碼方式進行測試或者與Ant結合.
  
  編碼方式
  DBUnit框架提供了一個基本的抽象測試用例類,叫做DatabaseTestCase,它是JUnit框架中的基礎類TestCase的子類。假如我們使用這個類必須首先實現兩個鉤子方法(hook
  methods):getConnection()和getDataSet().
  
  方法getConnection()需要返回一個IDatabaseConnection類型的對象,這個對象是一個基于普通JDBC連接的包裝類。例如,下面的代碼段演示了在MySQL數據庫環境下,IDatabaseConnection類型連接對象的創建方法。
  
  PRotected IDatabaseConnection getConnection()
  throws Exception {
  
  Class driverClass = Class.forName("org.gjt.mm.mysql.Driver");
  
  Connection jdbcConnection = DriverManager.getConnection(
  
  "jdbc:mysql://127.0.0.1/hr", "hr", "hr");
  
  return new DatabaseConnection(jdbcConnection);
  }
  
  方法getDataSet()返回一個IDataSet類型對象,其實,說白了,他就是我們先前提到的XML數據的種子文件的另一種表現形式。
  
  protected IDataSet getDataSet() throws Exception {
  return new FlatXmlDataSet(
  new
  FileInputStream("hr-seed.xml"));
  }
  
  有了這兩個基本的方法以后,DBUnit就可以按照它預先缺省的行為工作了。DatabaseTestCase類提供了兩個fixture(我叫它固件,不知仁兄同意否?)方法來控制測試前和測試后的數據庫狀態。這兩個方法就是:
  getSetUpOperation() 和 getTearDownOperation().
  
  一種高效的實施方案就是讓getSetUpOperation()方法執行REFRESH操作,通過這個操作,我們可以用種子文件中的數據去更新目標數據庫里的數據。接下來,就是getTearDownOperation(),讓他去執行一個NONE操作,也就是什么也不執行。
  
  protected DatabaSEOperation getSetUpOperation()
  throws
  Exception {
  return DatabaseOperation.REFRESH;
  }
  
  protected DatabaseOperation getTearDownOperation()
  throws
  Exception {
  return DatabaseOperation.NONE;
  }
  
  還有一種有效的方法就是在getSetUpOperation()方法中執行CLEAN_INSERT操作,這樣首先會將目標數據庫中與我們提供的種子文件一致的數據刪除,然后將我們提供的數據插入到數據庫中。這個實施順序保證了我們對數據庫的精確控制。
  
  代碼樣例
  在一個基于J2EE的人力資源系統中,我們很希望對某個數據操作周期實現測試自動化,這個操作周期包括職員的新增,檢索,更新和刪除。遠程接口定義了下列的業務方法(為了簡潔清楚,省略了方法中的throws子句).
  
  //譯者注:這里的EmployeeValueObject類型對象,譯者認為是代表職員實體信息的對象。
  
  public void  createEmployee( EmployeeValueObject emplVo )
  
  public EmployeeValueObject  getEmployeeBySocialSecNum( String ssn )
  
  public void  updateEmployee( EmployeeValueObject emplVo )
  
  public void  deleteEmployee( EmployeeValueObject emplVo )
  
  測試getEmployeeBySocialSecNum()方法
  需要植入一條數據到目標數據庫中,另外,測試deleteEmployee()方法和updateEmployee()方法時,同樣也是在先前植入的這條記錄的基礎上進行。最后,測試類會首先利用createEmployee()方法創建一條記錄,同時我們需要校驗執行這個方法時,是否會有異常發生。
  
  下面這個DBUnit種子文件,叫做"employee_hr_seed.xml",下面將用到這個文件。
  
  <?xml version='1.0' encoding='UTF-8'?>
  <dataset>
  <EMPLOYEE employee_uid='1'
  start_date='2001-01-01'
  first_name='Drew' ssn='333-29-9999'
  last_name='Smith' />
  <EMPLOYEE employee_uid='2'
  start_date='2002-04-04'
  first_name='Nick' ssn='222-90-1111'
  last_name='Marquiss' />
  <EMPLOYEE employee_uid='3'
  start_date='2003-06-03'
  first_name='Jose' ssn='111-67-2222'
  last_name='Whitson' />
  </dataset>
  
  測試類 EmployeesessionFacadeTest
  ,需要擴展DBUnit的基礎類DatabaseTestCase并且必須提供對getConnection()和getDataSet()方法的實現,在getConnection()方法中將獲得與EJB容器初始化時一樣的數據庫實例,getDataSet()方法負責讀取上面提及的employee_hr_seed.xml文件的數據。
  
  
  測試方法相當簡單,因為DBUnit已經為我們處理了復雜的數據庫生命周期任務。為了測試getEmployeeBySocialSecNum()方法,只需要簡單的傳遞一個存在于種子文件中的社保代碼號即可,比如
  "333-29-9999".
  
  //譯者注:EmployeeFacade 類型對象,譯者認為是代表底層數據庫數據的映射體
  
  public void testFindBySSN() throws Exception{
  
  EmployeeFacade facade = //oBTain somehow
  
  EmployeeValueObject vo =
  facade.getEmployeeBySocialSecNum("333-29-9999");
  
  TestCase.assertNotNull("vo shouldn't be null", vo);
  TestCase.assertEquals("should be Drew",
  "Drew", vo.getFirstName());
  TestCase.assertEquals("should be Smith",
  "Smith", vo.getLastName());
  }
  
  為了確保操作周期中的創建職員方法createEmployee()沒有問題,我們只需簡單的執行一下這個方法,然后校驗一下看有沒有異常拋出,另外,下一步我們要做的就是在這條新增的記錄上進行查找操作,看是否可以找到剛創建的記錄。
  
  public void testEmployeeCreate() throws Exception{

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产亚洲精品久久久久久| 97视频在线观看免费高清完整版在线观看| 在线播放日韩精品| 成人疯狂猛交xxx| 亚洲男人的天堂在线| 国产成人小视频在线观看| 欧美日韩一区二区精品| 性色av一区二区咪爱| 亚洲男人av在线| 日韩精品在线观看一区二区| 久久伊人91精品综合网站| 一区国产精品视频| 久久久精品一区二区| 永久555www成人免费| 久久手机免费视频| 亚洲精品一区二区三区不| 成人亚洲综合色就1024| 亚洲专区在线视频| 日韩视频第一页| 国产精品午夜视频| 日韩精品免费一线在线观看| 少妇高潮久久77777| 97在线看免费观看视频在线观看| 日韩中文字幕久久| 日韩av在线免费| 亚洲欧洲在线看| 精品免费在线视频| 国产成+人+综合+亚洲欧洲| 国内免费精品永久在线视频| 高清日韩电视剧大全免费播放在线观看| 日韩国产欧美精品在线| 午夜精品久久久99热福利| 久久av资源网站| 91中文字幕一区| 国产精品狠色婷| 在线激情影院一区| 在线观看国产精品91| 亚洲视频在线免费观看| 国产91精品久久久久久| 亚洲精选中文字幕| 亚洲天堂第一页| 亚洲a中文字幕| 最近2019免费中文字幕视频三| 在线播放国产精品| 久久99热这里只有精品国产| 欧美精品久久久久久久免费观看| 国产精品海角社区在线观看| 亚洲自拍偷拍区| 久久久久久久久亚洲| 在线观看国产精品淫| 精品无人国产偷自产在线| 亚洲国产精品va| 精品国内亚洲在观看18黄| 欧美最猛黑人xxxx黑人猛叫黄| 成人日韩在线电影| 91精品国产自产在线老师啪| 国产精品久久97| 亚洲精品一区二区三区婷婷月| 在线观看精品自拍私拍| 这里只有精品久久| 久久大大胆人体| 国产精品一区av| 亚洲欧美日韩综合| 日韩高清av一区二区三区| 蜜臀久久99精品久久久久久宅男| 亚洲人成亚洲人成在线观看| 超碰91人人草人人干| 欧美高清视频免费观看| 国产精品免费看久久久香蕉| 青青a在线精品免费观看| 成人精品一区二区三区电影免费| 国内偷自视频区视频综合| 国产91久久婷婷一区二区| 亚洲欧美日韩国产成人| 中文精品99久久国产香蕉| 亚洲国产高清自拍| 日韩电影免费在线观看| 欧美色videos| 国产精品成久久久久三级| 国产精品三级在线| 久久精品色欧美aⅴ一区二区| 国产色婷婷国产综合在线理论片a| 精品香蕉在线观看视频一| 久久精品国产99国产精品澳门| 国产一区二区三区网站| 欧美乱大交xxxxx| 亚洲精品中文字幕女同| 日韩在线视频免费观看| 91国内免费在线视频| 国产亚洲精品久久久久动| 欧美激情视频给我| 亚洲精品第一页| 视频在线一区二区| 韩国视频理论视频久久| 国产精品香蕉av| 精品国产欧美成人夜夜嗨| 国产美女主播一区| 一区二区国产精品视频| 日韩免费av片在线观看| 国产精品久久久久久影视| 欧美视频一区二区三区…| 57pao成人永久免费视频| 亚洲国产91精品在线观看| 亚洲欧洲在线免费| 日韩在线观看免费高清完整版| 久久99亚洲热视| 91免费人成网站在线观看18| 26uuu另类亚洲欧美日本老年| 亚洲精选一区二区| 亚洲一区二区免费在线| 久久亚洲国产精品成人av秋霞| 久久中文字幕一区| 欧美性感美女h网站在线观看免费| 欧美成人sm免费视频| 色综合色综合久久综合频道88| 精品中文字幕久久久久久| 国产精品1区2区在线观看| 国产精品99蜜臀久久不卡二区| 欧美丰满少妇xxxx| 成人免费在线网址| 色偷偷91综合久久噜噜| 在线免费观看羞羞视频一区二区| 亚洲精品电影久久久| 国产精品午夜国产小视频| wwwwwwww亚洲| 在线观看国产精品91| 国产91成人在在线播放| 日韩电影中文字幕| 精品久久久久久久久久久久| 欧美性猛交99久久久久99按摩| 国产日韩精品在线观看| 亚洲最大成人免费视频| 国产91对白在线播放| 美女撒尿一区二区三区| 深夜精品寂寞黄网站在线观看| 欧美亚洲日本网站| 在线电影av不卡网址| 亚洲欧美综合精品久久成人| 97久久精品人人澡人人爽缅北| 亚洲国产一区二区三区在线观看| 黄色精品一区二区| 岛国av一区二区三区| 美女国内精品自产拍在线播放| 亚洲男人天天操| 国模私拍一区二区三区| 欧美精品在线视频观看| 日本一区二三区好的精华液| 欧美精品videofree1080p| 色综合久久精品亚洲国产| 欧美日韩国产精品一区| 国产精品视频午夜| 欧美电影在线观看| 日韩av在线不卡| 97不卡在线视频| 91干在线观看| 亚洲欧美日韩精品久久奇米色影视| 亚洲免费人成在线视频观看| 国产三级精品网站| 久久免费高清视频| 欧美成人黑人xx视频免费观看| 成人美女免费网站视频| 日韩精品欧美国产精品忘忧草| 欧美激情性做爰免费视频| 日韩久久精品成人|