天天看點

AppFuse學習筆記-單元測試

    AppFuse為幾乎每一個類都提供了單元測試, 它使用JUnit架構進行測試。我們還是以User為例仔細分析一下,閱讀本篇的内容之前,你至少應該已經對單元測試有一個概念。

1. DAO測試

    UserDAOTest用于測試UserDAO這個接口和它的實作UserDAOHibernate,它在test/daodao/中。

    所有的DAOTest都繼承自BaseDAOTestCase,BaseDAOTestCase繼承自TestCase。這個父類已經為我們寫好了從Spring加載ApplicationContext的方法。

    setUp()裡做了在測試之前的初始化工作,建立了UserDAO和RoleDAO的執行個體,tearDown()裡做銷毀工作,這是每個Junit測試類都要做的事。

    以testUpdateUser()方法為例,該方法主要用于測試UserDAO的saveUser()方法是否正确。首先調用getUser()獲得使用者“tomcat”的資訊,并修改其位址,然後調用saveUser()方法儲存修改的記錄。重新獲得“tomcat”的資訊,校驗其位址是否為新位址,如果位址為新位址,測試成功。接下來把“tomcat”的version屬性的值置空(version為驗證目前記錄是否為新記錄的标志,null表示新紀錄),重新儲存“tomcat”,此時hibernate會認為該記錄為新記錄,進行insert操作,但username字段為主鍵不能重複,是以應該抛出異常。如果捕獲到異常,測試成功。

    在控制台進入項目根目錄,鍵入ant test-dao -Dtestcase=UserDAO,如果出現BUILD SUCCESSFUL,說明測試成功。這樣,我們不需要寫Manager、Action、JSP,不需要運作容器也可以確定我們的類正确了。

2. Manager測試

    接下來繼續看測試UserManager的類UserManagerTest。它在test/serviceservice/中,繼承自BaseManagerTestCase,這個父類起着與BaseDAOTestCase類似的作用。

    與UserDAOTest不同的是UserManagerTest使用了jMock幫助其測試。jMock用于解決UserManager的依賴,因為UserManager中需要調用UserDAO的方法,而單元測試的基本規則是一次隻測試一個對象,jMock幫助你把UserManager孤立起來,使它不會受到UserDAO的影響,我們來看它到底怎麼做。

    在setUp()裡,我們把UserDAO和RoleDAO放到Mock中,讓Mock來做UserDAO和RoleDAO的代理,并将這兩個“假冒的”DAO注入到UserManager中。

    還是以testSaveUser()為例來看這個test類怎麼工作。首先建立User對象,設定使用者名為“tomcat”,權限為“user”。然後我們告訴Mock當UserManager調用UserDAO的getUser()方法并參數是“tomcat”時,我們期待UserDAO傳回我們剛剛建立的那個對象。接下來調用UserManager的getUser()方法以獲得“tomcat”的資訊。修改電話号碼的内容。然後重置我們對Mock的要求。這次我們要求當UserManager調用UserDAO的saveUser方法時,不傳回任何值。然後調用UserManager的saveUser()方法,校驗user是否為新的電話号碼和權限是否還是一個,若是,測試成功。verify()用于檢查所有應該調用的方法是否都被調用了。通常來說,每對Mock對象調用了一次expects(),使用完後都要執行一次verify()。

    在控制台執行ant test-service -Dtestcase=UserManager,看看結果。

3. Action測試

    我們繼續看test/webaction下的UserActionTest。它繼承自BaseStrutsTestCase,BaseStrutsTestCase繼承MockStrutsTestCase,這個父類也做了類似BaseManagerTestCase的工作。

    Action是一個控制器,主要用于接收視圖層的請求,調用模型層的方法,然後傳回視圖層。在這裡我們不關心模型層或視圖層,我們隻要關心Action是否能夠正确的得到請求和響應請求,以及能夠正确的根據請求轉向。MockStrutsTestCase給了我們測試這方面很好的支援。

    以testSave()為例,首先建立一個UserForm,在裡面放入部分資料,将UserForm放入該Action所對應的範圍内。使用setRequestPathInfo()設定請求路徑為“/saveUser”,使用addRequestParameter()添加好請求參數,actionPerform()方法将模拟請求的全過程。然後使用verifyForward()方法驗證請求轉發路徑是否正确。并驗證能不能在Action範圍内得到UserForm。

    運作ant test-web -Dtestcase=UserAction,OK。

    要注意一點,這裡的單元測試雖然繼承自MockStrutsTestCase,但沒有使用Mock,也就是說,它會真正執行到所有相關的方法,包括修改資料庫。

4. JSP測試

    我們同樣可以對JSP進行測試。這裡有一個工具叫做Canoo WebTest,它使用xml配置的方式來測試JSP。

    進入test/web/,有一個web-tests.xml檔案,裡面有所有struts-config.xml中存在的path的測試。

    以SaveUser這個target為例,我們做一個簡單的說明。測試步驟包含在steps中,invoke中給這個step定一個ID号,設定請求的url:editProfile.html。接下來驗證JSP頁面的title是否與預期的一緻。其中{webapp.prefix}和{userProfile.title}的内容在WEB-INF/classes中的ApplicationResources中定義。接下來給表單中的文本域填寫内容,使用clickbutton點選儲存按鈕,驗證儲存後的頁面标題是否為預期的标題。

    這一測試需要運作容器,是以首先運作Tomcat,再在控制台鍵入ant test-canoo -Dtestcase=UserTests或ant test-jsp -Dtestcase=PersonTests。使用ant run-all-tests無需運作Tomcat,Ant為你做這件事。