熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

Struts測試框架StrutsTestCase實戰

2013-11-23 20:03:12  來源: Java開源技術 
閱讀提要 StrutsTestCase是一個強有力的易於使用的針對Struts行為的測試框架StrutsTestCase並與傳統型JUnit測試相結合將會帶給你一個相當高的測試覆蓋率並提高你的產品的可靠性

  引言

  StrutsTestCase是一個用於測試Struts行為的基於Junit的測試框架如果你使用Struts那麼你會注意到它可以提供給你一種容易而有效的方式來測試你的應用程序的Struts行為類

  典型的JEE應用程序都是分層構建的如圖所示

  ·DAO層封裝了數據庫存取Hibernate映射和對象類Hibernate查詢實體EJBs或一些其它的實體關系持續性技術都可以在這一層找到

  ·商業層包含更高級的商業服務理想地這個商業層將是相對獨立於數據庫實現在這個層上經常使用會話EJBs

  ·描述層包含為用戶顯示應用程序數據並解釋用戶請求在一個Struts應用程序中這一層典型地使用JSP/JSTL頁面來顯示數據並且使用Struts行為來解釋用戶查詢

  ·客戶層基本上是運行於用戶機器上的web浏覽器客戶端邏輯(例如JavaScript)有時被放在這裡盡管很難對其進行有效地測試



典型的JEE架構
  DAO和商業層的測試或者可以通過使用經典的JUnit測試或者使用各種JUnit擴展來進行具體依賴於架構的實現細節DbUnit是一種用來進行數據庫單元測試的良好選擇

  另一方面測試Struts行為總是很困難的事情即使在商業層嚴格地限制於商業層的構建時Struts行為也總要包含重要數據校驗轉換和流程控制代碼不對Struts行為進行測試將會在代碼覆蓋率上留下一道很髒的鴻溝StrutsTestCase會讓你填充這條鴻溝

  對行為層進行單元測試還帶來其它一些益處

  ·可以更好地規劃視圖和控制層從而使之更為簡單清晰

  ·更容易重構行為類

  ·避免冗余的未使用的行為類

  ·測試實例有助於對行為層進行歸檔這在創建屏幕時是很有用的

  上面是基於測試開發的典型好處並且它們可以應用於在各種情況下使用的Struts行為層

  StrutsTestCase簡介

  StrutsTestCase工程提供了一種靈活又方便的方法來從JUnit框架內測試Struts行為它能夠使你對你的Struts行為進行白色盒子測試通過在調用行為後建立請求參數並檢查結果Request或Session的狀態

  StrutsTestCase允許或者是一個模仿測試方式這時框架模擬web服務器容器或者是一個容器內方式這時使用Cactus框架來從服務器容器(例如Tomcat)內部運行測試一般地我比較喜歡模仿測試方式因為它更為輕量級的且運行更快些並因此允許較寬松的開發周期
所有的StrutsTestCase單元測試類或者派生於MockStrutsTestCase以進行模仿測試或者派生於CactusStrutsTestCase以進行容器內測試在此我們先討論模仿測試因為它要求較少的配置並且運行較快些

  實戰StrutsTestCase

  為了使用StrutsTestCase來測試這個行為我們創建一個擴展類MockStrutsTestCase的新類這個類提供一系列方法來構建一個模擬的HTTP請求調用相應的Struts行為以及一旦在行為完成時校驗應用程序狀態

  可以設想有一個在線的具有多條件查找功能的住所數據庫這個查找函數是通過/searchdo行為實現的這個行為將基於指定的條件完成一次多條件查找並把結果列表放置在一個稱為results的請求范圍屬性中例如下列URL應該顯示一個在法國的所有的住所結果列表
/searchdo?country=FR

  現在假定我們想要使用一個測試驅動的方式來實現這個方法我們創建該行為類並更新Struts配置文件我們還編制測試實例來測試(空的)這個行為類通過使用一種嚴格的測試驅動的開發方法我們可以首先創建測試實例然後實現代碼來匹配該測試實例在實踐中具體的順序可能因要測試的代碼而有所不同

  起始的測試情形看去如下樣子

public void testSearchByCountry() {
 setRequestPathInfo(/searchdo);
 addRequestParameter(country FR);
 actionPerform();
}
  在此我們建立要調用的路徑(setRequestPathInfo())並且添加一請求參數(addRequestParameter())然後我們用actionPerform()來調用行為類這將驗證Struts配置並且調用相應的行動類但是將不測試該行為的實際所做為此我們需要驗證行動的結果

public void testSearchByCountry() {
 setRequestPathInfo(/searchdo);
 addRequestParameter(country FR);
 actionPerform();
 verifyNoActionErrors();
 verifyForward(success);
 assertNotNull(requestgetAttribute(results));
}
  在此我們檢查三件事情

  ·不存在ActionError消息(verifyNoActionErrors())

  ·返回successforward

  ·results屬性被放置到請求范圍中

  如果我們正在使用tiles我們也可以通過使用verifyTilesForward()來保證successforward實際上指定正確的tiles定義

public void testSearchByCountry() {
 setRequestPathInfo(/searchdo);
 addRequestParameter(country FR);
 actionPerform();
 verifyNoActionErrors();
 verifyTilesForward(success accommodationlistdef);
 assertNotNull(requestgetAttribute(results));
}
  在實踐中我們可能想在該測試結果上實現特定的商業測試例如假定結果屬性是一個List它包含一列約個Hotel域對象並且我們想要保證所有在該列表中的賓館都在法國為了實現這種類型的測試代碼將非常相似於標准JUnit測試

public void testSearchByCountry() {
 setRequestPathInfo(/searchdo);
 addRequestParameter(country FR);
 actionPerform();
 verifyNoActionErrors();
 verifyForward(success);
 assertNotNull(requestgetAttribute(results));
 List results = (List) requestgetAttribute(results);
 assertEquals(resultssize() );
 for (Iterator iter = erator();
 iterhasNext();) {
  Hotel hotel = (Hotel) iternext();
  assertEquals(hotelgetCountry TestConstantsFRANCE);
  
 }
}
  當你測試更復雜的情形時你可能想要測試系列化的行為例如假定用戶在法國查詢所有的賓館並且點擊一個入口來顯示相應的查詢細節假定我們有一個Struts行為來顯示一個給定賓館的細節信息可以作如下調用

/displayDetailsdo?id=

  通過使用StrutsTestCase我們能夠容易地在相同的測試情形下模仿一系列的行為一個用戶在法國查詢所有的賓館然後點擊一個入口來顯示相應的查詢細節

public void testSearchAndDisplay() {
 setRequestPathInfo(/searchdo);
 addRequestParameter(country FR);
 actionPerform();
 verifyNoActionErrors();
 verifyForward(success);
 assertNotNull(requestgetAttribute(results));
 List results = (List) requestgetAttribute(results);
 assertEquals(resultssize());
 Hotel hotel = (Hotel) resultsget();
 setRequestPathInfo(/displayDetailsdo);
 addRequestParameter(id hotelgetId());
 actionPerform();
 verifyNoActionErrors();
 verifyForward(success);
 Hotel hotel = (Hotel)requestgetAttribute(hotel);
 assertNotNull(hotel);
 
}
  測試Struts錯誤處理

  測試錯誤處理也是一件很重要的事情假定如果指定一個無效的國家代碼時我們想要檢查應用程序仍然運行良好為此我們可以寫一個新的測試方法並且使用verifyActionErrors()檢查返回的Struts ErrorMessages:

public void testSearchByInvalidCountry() {
 setRequestPathInfo(/searchdo);
 addRequestParameter(country XX);
 actionPerform();
 verifyActionErrors( new String[] {errorunknowncountry});
 verifyForward(failure);
}
  有時你想直接在ActionForm對象中進行數據校驗為此你可以使用getActionForm()如下所示:

public void testSearchByInvalidCountry() {
 setRequestPathInfo(/searchdo);
 addRequestParameter(country XX);
 actionPerform();
 verifyActionErrors( new String[] {errorunknowncountry});
 verifyForward(failure);
 SearchForm form = (SearchForm) getActionForm();
 assertEquals(Scott formgetCountry(XX));
}
  在此我們可以確保在出現錯誤後無效的國家代碼被正確地存儲在ActionForm中

  定制測試環境

  重載setUp()方法有時是很有用的它讓你指定非缺省的配置選項在這個例子中我們使用一個不同的strutsconfigxml文件並且不激活XML配置文件校驗:

public void setUp() {
supersetUp();
setConfigFile(/WEBINF/mystrutsconfigxml);
setInitParameter(validatingfalse);
}
  第一級性能測試

  測試一個行為或一系列的行為是一個十種優秀的測試方式它要求能夠存取響應次數從Struts行為中進行測試允許你校驗全局的服務器端性能(當然除去產生JSP頁面)為了盡快隔離和移除性能問題以及把它們集成到構建過程中以幫助避免性能回退在單元測試級上進行一些第一級性能測試是個很不錯的注意

  下面是我用來進行第一級Struts性能測試的基本原則:

  ·用盡可能多的組合來測試多條件搜索查詢(為了檢查這些索引已被正確定義了)

  ·測試大容量的查詢(返回大量結果的查詢)來檢查響應次數和結果頁面(如果使用的話)

  ·測試單個的和重復的查詢(來檢查緩沖性能如果使用緩沖策略的話)

  有一些開源庫可以用於幫助進行性能測試例如由Mike Clark維護的JUnitPerf然而把它們集成到StrutsTestCase中可能有些復雜在很多情況下一個簡單的定時器即可以實現這一功能下面是一種簡單而有效的實現第一級性能測試的方法

public void testSearchByCountry() {
 setRequestPathInfo(/searchdo);
 addRequestParameter(country FR);
 long t = SystemcurrentTimeMillis();
 actionPerform();
 long t = SystemcurrentTimeMillis() t;
 logdebug(Country search request processed in + t + ms);
 assertTrue(Country search too slow t >= )
}
  結論

  一般地單元測試是進行靈敏編程特別是基於測試開發的一個基本部分StrutsTestCase為我們提供一種容易並且有效的方法來單元測試Struts行為否則如果使用JUnit來進行單元測試則相當困難
From:http://tw.wingwit.com/Article/program/Java/ky/201311/27868.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.