SOA 環境中的測試驅動的開發,第 1 部分: 測試資料對映

CloudSpace發表於2009-06-03

引言

在軟體工程方面,兩個最近的重大變化是對測試驅動的開發和持續整合的使用日益增加。作為轉向敏捷軟體開發方法的一部分,這些實踐已在基於 Java™ 的傳統應用程式開發中使用了許多年,最近開始用於 SOA 解決方案的開發。

為此,一篇最近的 developerWorks 文章描述了 IBM WebSphere Integration Developer V6.1 的一個新功能,該功能使您能夠建立測試用例,並且只需單擊一個按鈕即可在無人蔘與的情況下執行它們。另一個文章系列闡述瞭如何使用 JUnit 和 Cactus 來測試服務元件體系結構(Service Component Architecture,SCA)元件、BPEL 元件和人工任務。這些文章對在 SOA 環境中工作的所有 Java 開發人員都非常有幫助。為了補充那些資源,這個由兩部分組成的文章系列將研究兩個同等重要的附加主題:

  • 資料對映的單元測試在 SOA 專案的早期階段中極其有用。測試資料對映對於不成熟的服務介面(其中資料要麼還沒有很好地建立,要麼不穩定)來說是必需的,並且對於較成熟的服務介面也非常有用。這些測試將使您能夠不必太關心重構資料型別。您可以做出一些更改,重新測試對映,然後重新測試使用這些對映的模組。

  • 持續整合是每天執行多次的完全自動化和可再現的構建(包括測試),是用於傳統應用程式並得到廣泛認可的開發實踐。要對 SOA 環境應用這種敏捷開發實踐,您需要能夠作為定期計劃的整合構建的一部分執行單元測試。這是在諸如 WebSphere Integration Developer 等整合開發環境 (IDE) 之外進行的,因此一般需要通過 Ant 執行單元測試。

本文向您說明如何獨立於使用資料對映的 SCA 模組對資料對映進行測試。通過使您能夠在釋出庫以供模組使用之前對庫進行測試,資料對映測試對在共享庫中定義公共資料型別和資料對映的標準實踐形成了補充。您甚至可以在建立任何模組之前對庫進行測試。這與測試驅動的開發實踐是一致的。

第二部分將介紹如何在 SOA 環境中使用持續整合,使用諸如 Ant 等自動化構建工具來執行單元測試,生成測試報告,並在測試失敗的情況下向開發人員傳送電子郵件。

對資料對映進行單元測試

為了瞭解如何測試資料對映,請考慮以下場景:

  • 您有一個地址清理服務,它檢查地址的有效性,但是需要給出一個地址作為被逗號分隔的值;也就是說,庫中存在一種 AddressCSV 資料型別。

  • 該 SOA 解決方案的其他部分要求地址使用單獨的欄位來表示地址元素,例如 company、addressLine1,等等;也就是說,庫中存在一種 Address 資料型別。

  • 該庫具有兩個資料對映,其中一個從 Address 對映到 AddressCSV(圖 1),另一個從 AddressCSV 對映到 Address(圖 2)。



    圖 1. Address_To_AddressCSV 資料對映
    圖 1. Address_To_AddressCSV 資料對映



    圖 2. AddressCSV_To_Address 資料對映
    圖 2. AddressCSV_To_Address 資料對映

可以看出,上述對映相當簡單,逐個欄位的對映是相對簡單的。然而,對於大型業務物件,對映可能相當複雜,辨別屬性彼此間的對映通常變得非常困難。建立資料對映可能是非常繁瑣且很容易出錯的任務,從而突出了重複測試的重要性。

要測試上述資料對映,您通常要編寫兩個 JUnit 測試用例。對於此示例場景,為您提供了程式碼示例以供下載。該示例程式碼在一個專案交換檔案中,您可以將該檔案匯入 WebSphere Integration Developer V6.1 工作區。匯入以後,開啟 Business Integration 透檢視檢視三個示例專案:

  • L_AddressCleansingService:此庫具有用於組合應用程式的資料型別和資料對映,並將由構成 SOA 解決方案的模組重用。
  • T_AddressCleansingService:此模組用於測試資料對映,並將僅部署到測試環境中的 IBM WebSphere Process Server。它不是 SOA 解決方案的一部分。
  • T_AddressCleansingServiceJUnitWeb:此動態 Web 專案包含了將在 WebSphere Process Server 容器中執行的 Junit 測試用例。它是 T_AddressCleansingService 測試模組的一部分。

此場景假設該庫的資料型別和對映已經存在,因此本文將不介紹如何建立它們。您可以檢視該庫以瞭解它們的定義。有關如何建立資料對映的資訊,您還可以檢視這個 WebSphere Integration Developer 指導教程

本文的其餘內容將研究用於測試資料對映的三個大致步驟:

  1. 建立測試模組和 Web 專案
  2. 建立測試用例和資料對映
  3. 執行測試用例

下面幾個部分將詳細描述這些步驟。

1. 建立測試模組和 Web 專案

對於此步驟,您可以選擇按照以下說明操作或下載並匯入專案交換檔案,以便能夠使用所提供的測試模組和 Web 專案。如果您選擇後者,請向前跳到步驟 2

要建立測試模組,請執行以下步驟:

  1. 在 WebSphere Integration Developer 的 Business Integration 透檢視中,開啟 Business Integration 檢視。請單擊右鍵,然後選擇 New => Module。在 New Module 對話方塊中,輸入名稱 T_AddressCleansingService,然後單擊 Finish

  2. 要建立動態 Web 專案,請切換到 J2EE 透檢視。右鍵單擊 T_AddressCleansingServiceApp 並選擇 New => Dynamic Web Project。在 New Dynamic Web Project 對話方塊中,輸入 T_AddressCleansingServiceJUnitWeb 並單擊 Finish

  3. 下一步,建立測試模組與包含有要對映的資料型別和要測試的資料對映的庫之間的關聯。為此,請切換到 Business Integration 透檢視。選擇 T_AddressCleansingService 並雙擊開啟 Dependency 編輯器。展開 Libraries 並使用 Add 功能新增 L_AddresCleansingService。

  4. 接下來,您需要將 Log4J、Junit 和 Cactus 框架新增到測試模組。為此,將以下庫新增到 T_AddressCleansingServiceJUnitWeb 專案的 web-inf\lib 資料夾:

  5. 最後,您需要將 Cactus Servlet 定義新增到 Web 應用程式中的 web.xml 檔案。為此,請剪下清單 1 中的程式碼,並將其直接貼上到動態 Web 應用程式部署描述符中的現有描述和歡迎檔案之間:



    清單 1
    						
    T_AddressCleansingServiceJUnitWeb
    
            
                    ServletRedirector
                    
                           org.apache.cactus.server.ServletTestRedirector
                    
                    
    	           param1
    	            value1 used for testing
    	   
            
    
            
                    ServletTestRunner
                    
                            org.apache.cactus.server.runner.ServletTestRunner
                    
            
    	
            
    	    ServletRedirector
    	    /ServletRedirector
            
    	
            
    	    ServletTestRunner
    	    /ServletTestRunner
            
    
            

2. 建立測試用例和資料對映

下一步,您將為 Address_To_AddressCSV 資料對映編寫測試用例。您的測試用例將填充一個輸入的 Address 物件,呼叫該對映以產生輸出 AddressCSV 物件,然後將最終獲得的 AddressCSV 物件與預期的結果做比較。如果它們相等,則認為測試成功;如果它們不相等,則測試失敗。(所包括的專案交換檔案還包含一個用於 AddressCSV_To_Address 對映的單元測試用例。)

建立單元測試涉及到以下步驟:

  1. 建立測試用例

    典型的 JUnit 程式設計模型通過擴充套件 JUnit 提供的 TestCase 類建立測試類。Cactus 框架是 JUnit 的擴充套件,Junit 使您能夠在一個容器中執行單元測試。由於您是在使用 Cactus 框架,您將擴充套件 Cactus 測試類 org.apache.cactus.ServletTestCase。為此,請執行以下操作:

    1. 轉到 Web 透檢視中的 Project Explorer 檢視,展開 Dynamic Web Projects => T_AddressCleansingServiceJUnitWeb => Java Resources => JavaSource
    2. 右鍵單擊 Java Source,並選擇 New => Package 以建立適當的包。右鍵單擊該包,選擇 New => Class 以建立類,並輸入如下程式碼:

      清單 2
      								
      package com.ibm.issw.service.addresscleansing.test;
      
      import org.apache.cactus.ServletTestCase;
      
      public class AddressCleansingServiceTest extends ServletTestCase {

  2. 編寫 setup() 和 teardown() 方法

    JUnit 框架為您提供了相關方法,您可以實現這些方法來為測試用例設定環境,並在執行測試用例以後銷燬該環境。其中的事件序列如下:呼叫 setUp(),呼叫 testxxx() 方法,呼叫 tearDown()。該測試類中的每個 testXXX() 方法都將發生此事件序列。清單 3 顯示了示例 setUp() 和 tearDown() 方法。



    清單 3
    						
    private DataObject expectedAddress;
    private String expectedWholeAddress;
    private DataObject expectedAddressCSV;
    private MapService mService;
    
    private static Logger logger = Logger.getLogger(
        AddressCleansingServiceTest.class );
    
    protected void setUp() throws Exception {
        expectedAddress = createAddress(
            "IBM Corporation","1133 Westchester Avenue",
            "","White Plains","NY","10604");
        expectedWholeAddress = createWholeAddress(
            "IBM Corporation","1133 Westchester Avenue",
            "","White Plains","NY","10604");
        expectedAddressCSV = createAddressCSV(expectedWholeAddress);
    		
        // Get the map service so we can invoke the mapping operation.
        mService = (MapService) ServiceManager.INSTANCE.locateService(
            "com/ibm/wbiserver/map/MapService");
    }
    
    protected void tearDown() throws Exception {
        expectedAddress = null;
        expectedAddressCSV = null;
        expectedWholeAddress = null;
        mService = null;
        }

    清單 3 顯示了以下內容:

    • 由測試方法共享的私有資料成員的定義。這些資料成員將在 setUp() 中初始化,在 testXX() 中使用,並在 tearDown() 中銷燬。
    • 日誌記錄服務的建立,以便您能夠在測試方法中記錄日誌。
    • “實際”輸入 SDO 的建立和初始化,以便您能夠通過 createAddress() 方法將其傳遞給該對映。這只是建立了一個 Address SDO 並將其初始化為給定的值。(請參見專案交換檔案以瞭解其實現。)
    • “預期的”輸出 SDO 的建立和初始化,以便您能夠將其與該對映返回的實際輸出做比較。這是通過 createWholeAddress() 和 createAddressCSV() 方法完成的。(請參見專案交換檔案以瞭解其實現。)
  3. 建立測試方法

    JUnit 命名約定規定所有測試方法名稱都應以單詞“test”開頭。這些方法不帶任何引數,是空方法。測試失敗通過引發未經檢查的異常來指示,通常是使用 JUnit 提供的斷言和故障方法。測試成功通過測試方法的完成來指示。此示例的測試方法類似於清單 4。



    清單 4
    						
    public void testAddress_To_AddressCSVMap() 
    throws WBIMapNotFoundException, WBIMapFailureException, WBIMapServiceException {
       try {
    	logger.debug("Invoking Address_To_AddressCSV map.");
    
    	BOFactory bof = (BOFactory)ServiceManager.INSTANCE.locateService(
             "com/ibm/websphere/bo/BOFactory");
    	DataObject actualAddressCSV = bof.create(
             "http://L_AddressCleansingService", "AddressCSV");
    
    	HashMap inputMap = new HashMap();
    	HashMap utputMap = new HashMap();
    	inputMap.put("Address", expectedAddress);
    	outputMap.put("AddressCSV", actualAddressCSV);
    	mService.transform("http://L_AddressCleansingService",
             "Address_To_AddressCSV", inputMap, outputMap, (ExecutionContext)null);
          assertEquals(actualAddressCSV.getString("wholeAddress"),
             expectedAddressCSV.getString("wholeAddress"));
       } catch (WBIMapNotFoundException e) {
          logger.debug("WBIMapNotFoundException: " + e.getMessage());
    	throw e;
       } catch (WBIMapFailureException e) {
    	logger.debug("WBIMapFailureException: " + e.getMessage());
    	throw e;
       } catch (WBIMapServiceException e) {
    	logger.debug("WBIMapServiceException: " + e.getMessage());
    	throw e;
       }
    }

    清單 4 顯示了以下內容:

    • 使用 Log4J 在測試過程中顯示某些訊息。請注意,Log4J.properties 檔案需要在類路徑上,以指定要使用的搜尋路徑,這裡是通過嚮應用程式伺服器的類路徑新增資料夾來實現的。為此,請執行以下步驟:
      1. 開啟管理控制檯。
      2. 導航到 Application servers => server1 => Process Definition => Java Virtual Machine
      3. 將您放置 log4j.properties 檔案的資料夾新增到類路徑,如清單 5 所示。


      清單 5
      								
      log4j.rootLogger=WARN, RootAppender, ConsoleAppender
      
      log4j.appender.ConsoleAppender=org.apache.log4j.ConsoleAppender
      log4j.appender.ConsoleAppender.layout=org.apache.log4j.PatternLayout 
      log4j.appender.ConsoleAppender.layout.ConversionPattern=[%d] %-5p %c{2} - %m%n
      
      log4j.logger.com.ibm.issw=DEBUG

    • 使用 transform() 方法呼叫資料對映。此示例中使用了通用的 transform() 方法,它可以呼叫將一個或多個 SDO 轉換為另一個 SDO 的對映,但是您也可以使用 simpleTransform() 方法呼叫資料對映,因為此方法從一個 SDO 轉換為另一個 SDO。清單 6 中的程式碼片段顯示瞭如何使用 simpleTransform()。

      清單 6
      								
      mService.simpleTransform(
         " http://L_AddressCleansingService”,
         "Address_To_AddressCSV"
         input,
         output);

    • 有關該操作返回的資料的一連串斷言;特別是,您將考慮對映的定義幷包括有關每個轉換的斷言。為此,您將使用輸入和輸出資料物件上的 get 方法,並使用 JUnit assertEquals()。

有了此程式碼後,您就做好了執行測試的準備。

3. 執行測試用例

要執行測試,請執行以下操作:

  1. 首先,將測試模組新增到伺服器,並確保伺服器已啟動。

  2. 在 Business Integration 透檢視中,轉到 Servers 檢視。右鍵單擊伺服器,選擇 Add Remove Projects,並將 T_AddressCleansingServiceApp 新增到伺服器。您現在已經擁有了可用於執行的測試類。

  3. 要執行測試類,請轉到 J2EE 透檢視中的 Project Explorer 檢視。選擇 AddressCleansingServiceTest 類,然後從 Run 選單中選擇 Run...

  4. 在 Run 對話方塊中,從可能的 Configurations 列表中選擇 JUnit,然後單擊 New

  5. 選擇 Arguments 窗格。在 VM 引數下,輸入 -D 引數,如清單 7 所示。(此引數指定本地主機和埠 9083;如果您的伺服器或用於 HTTP 請求的埠與此不同,請根據需要調整此字串以匹配您的值。)

    -Dcactus.contextURL=http://localhost:9083/T_AddressCleansingServiceJUnitWeb
    

  6. 選擇 Run 來啟動測試。JUnit 檢視然後顯示執行測試的結果(圖 3)。



    圖 3. 執行測試的結果
    圖 3. 執行測試的結果

現在您已經建立了這個啟動配置,您只需選擇它並單擊 Run => JUnit Test 即可重複執行該類。

作者:Donald Vines, 執行 IT 架構師, IBM

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14789789/viewspace-604982/,如需轉載,請註明出處,否則將追究法律責任。

相關文章