Nicholas Lesiecki (ndlesiecki@apache.org) 主要軟件工程師,eBlox, Inc.
在開發過程中結合了單元測試的程序員都了解這樣做帶來的好處:代碼更簡潔,敢于重構、速度更快。但即便是最執著的單元測試者,在碰到測試行為依靠于系統狀態的類的情況時,也會顯得信心不足。Nicholas Lesiecki 是一名受人尊敬的 java 程序員,也是 XP 社區的領導者,他將介紹圍繞測試案例隔離的問題,并向我們展示如何使用模擬對象(mock object)和 aspectJ 來開發精確和健壯的單元測試。請通過單擊文章頂部或底部的討論,在討論論壇與作者和其它讀者分享您對本文的看法。 最近,人們對極端編程(Extreme PRogramming,XP)的關注已經擴大到它的一個最具可移植性的應用上:單元測試和最初測試設計。因為軟件工作室已經開始采用 XP 的開發方法,我們可以看到,因為有了一套全面的單元測試工具,很多開發者的開發質量和速度都得到了提高。但編寫好的單元測試耗時費力。因為每個單元都與其它單元合作,所以編寫單元測試可能需要大量的設置代碼。這使得測試變得更加昂貴,而且在特定情況下(比如代碼充當遠程系統的客戶機時),這樣的測試可能幾乎無法實現。
在 XP 中,單元測試彌補了集成測試和驗收測試的不足。后兩種測試類型可能由獨立的小組進行,或者作為獨立的活動進行。但是單元測試是與要測試的代碼同時編寫的。面對日益逼近的截止期限和令人頭痛的單元測試帶來的壓力,我們很可能隨便編寫一個測試了事,或者完全放棄測試。因為 XP 依靠于積極的動機和自給自足的習慣,所以 XP 過程(和項目?。┑淖罴牙婢褪鞘箿y試保持集中和易于編寫。
清單 1. CustomerManager 的遠程接口 public interface CustomerManager extends EJBObject {
/** * Returns a String[] representing the names of customers in the system * over a certain age. */ public String[] getCustomersOver(int ageInYears) throws RemoteException;
/** * Registers a new customer with the system. If the customer already * exists within the system, this method throws a NameExistsException. */ public void register(String name) throws RemoteException, NameExistsException; }
清單 2. EJB 客戶機代碼 public class ClientBean { private Context initialContext; private CustomerManager manager;
/** * Includes standard code for referencing an EJB. */ public ClientBean() throws Exception{ initialContext = new InitialContext(); Object obj = initialContext.lookup("java:comp/env/ejb/CustomerManager"); CustomerManagerHome managerHome = (CustomerManagerHome)obj;
/*Resin uses Burlap instead of RMI-IIOP as its default * network protocol so the usual RMI cast is omitted. * Mock Objects survive the cast just fine. */ manager = managerHome.create(); }
public String[] getCustomers(int ageInYears) throws Exception{ return manager.getCustomersOver(ageInYears); }
public static final String NEW_CUSTOMER = "Bob Smith"; public static final String EXISTING_CUSTOMER = "Philomela Deville"; public static final int MAGIC_AGE = 35;
public void testGetCustomers() throws Exception { ClientBean client = new ClientBean(); String[] results = client.getCustomers(MAGIC_AGE); assertEquals("Wrong number of client names returned.", 55, results.length); }
public void testRegisterNewCustomer() throws Exception{ ClientBean client = new ClientBean(); //register a customer that does not already exist boolean couldRegister = client.register(NEW_CUSTOMER); assertTrue("Was not able to register " + NEW_CUSTOMER, couldRegister); }
public void testRegisterExistingCustomer() throws Exception{ ClientBean client = new ClientBean();
//register a customer that DOES exist boolean couldNotRegister = ! client.register(EXISTING_CUSTOMER); String failureMessage = "Was able to register an existing customer (" + EXISTING_CUSTOMER + "). This should not be " + "possible." assertTrue(failureMessage, couldNotRegister); }
if("java:comp/env/ejb/CustomerManager".equals(name)){ return new MockCustomerManagerHome(); } else{ throw new Error("ClientBean should not lookup any EJBs " + "except CustomerManager"); } } }
[contents of objectReplacement.lst] @base.lst;[A reference to files included in both configurations] MockCustomerManagerHome.java MockCustomerManager.java ObjectReplacement.java.
Nicholas Lesiecki 的 Java Tools for Extreme Programming(與 Rick Hightower 合著)一書中介紹了可以幫助您實現 XP 方法(如單元測試和連續集成)的實用工具。幾乎本文中使用的所有工具(JUnit、Cactus 和 Ant)在這個出色的參考中都有所描述。
要了解更多關于模擬對象的信息,請訪問 mockobjects.com,或者看看最初開始討論它的文章“Endo Testing: Unit Testing with Mock Objects”(PDF 格式)。
developerWorks 上有很多關于開始使用 Ant 和 JUnit 的出色文章:請參考 Erik Hatcher 的“Automating the build and test process”(2001 年 8 月)和 Malcolm Davis 的“Incremental development with Ant and JUnit”(2000 年 11 月)。
假如您的測試需要超出單元測試的范圍,而達到企業級系統測試領域,請參閱 IBM Performance Management, Testing, and Scalability Services 站點,看看它能提供什么。(該站點包括一個關于企業測試的庫。)
假如您在使用 VisualAge for Java 作為 IDE,那么來自 VisualAge 開發者園地的 Unit testing with VAJ 展示了 JUnit 和 VAJ 如何結合成為強大的整體,用最小的努力達到全面的代碼測試。
您可以在 IBM developerWorks Java 技術專區上找到數百篇關于 Java 編程每個方面的文章。
關于作者 Nicholas Lesiecki 在互聯網正值繁榮時開始接觸到 Java,從那時起不斷成長為 XP 和 Java 社區的突出人物。Nicholas 目前領導 eBlox Inc. 的旗艦聯機目錄系統 storeBlox 的開發。除了頻繁地在 Tucson JUG 發表演說,他還保持 Jakarta 的 Cactus 工程的積極贊助人身份。Nick 與其它人合著了 Java Tools for Extreme Programming,一本關于在靈活的進程(如 XP)中利用開放源代碼構建和測試工具的使用指南手冊。Nick 希望感謝 Ron Bodkin、Wes Isberg 和 Vincent Massol 在撰寫本文的過程中提供的幫助。請通過 ndlesiecki@apache.org 與 Nick 聯系。