Struts測試之Mock Object測試

          Struts測試之Mock Object測試

          以下內容引自 http://www.xgdown.com/article/239/47289_1.htm

          使用Mock Object進行測試,主要是用來模擬那些在應用中不容易構造(如HttpServletRequest必須在Servlet容器中才能構造出來)或者比較復雜的對象(如JDBC中的ResultSet對象)從而使測試順利進行的工具。

          JMock

          簡介

          請訪問 http://www.jmock.org

          準備

          1.??????? 獲取 J2SDK

          2.??????? 獲取 JUnit V3.8.1 (從 http://www.junit.org 獲取開發包);

          3.??????? 獲取 JMock V1.0 (從 http://www.jmock.org 獲取 JMock 開發包)。

          4.??????? 為了開發方便,建議使用一個好 IDE 。以下例子中的代碼均是在 Eclipse V3.0 環境下進行的調試。

          例子一

          以下是一個簡單例子,代碼如下:

          package test1;

          ?

          import org.jmock.*;

          import javax.servlet.http.*;

          ?

          public class MockRequestTest extends MockObjectTestCase{

          ??? public void testMockRequest1(){

          ?????? // 構造一個 Mock 對象

          ??????? Mock mock = new Mock(HttpServletRequest.class);

          ???????

          ??????? // 設置要執行的操作,以下設置表示要調用一次 HttpServletRequest 對象的

          ??????? //getParameter 方法,傳遞的參數是 "name", 期望的返回是 "kongxx"

          ??????? mock.expects(once()).method("getParameter").with(eq("name")).will(returnValue("kongxx"));

          ???????

          ??????? // 根據 Mock 對象獲取一個 HttpServletRequest 對象

          ??????? HttpServletRequest request = (HttpServletRequest)mock.proxy();

          ???????

          ??????? // 斷言調用結果

          ??????? assertEquals("kongxx" ,request.getParameter("name"));???????

          ??? }

          ??? public void testMockRequest2(){

          ?????? // 構造一個 Mock 對象

          ??????? Mock mock = new Mock(HttpServletRequest.class);

          ???????

          ??????? // 設置要執行的操作,以下設置表示要調用一次 HttpServletRequest 對象的

          ??????? //getParameter 方法,傳遞的參數是 "name", 期望的返回是 "kongxx"

          ??????? mock.expects(once()).method("getParameter").with(eq("name")).will(returnValue("kongxx"));

          ???????

          ??????? // 根據 Mock 對象獲取一個 HttpServletRequest 對象

          ??????? HttpServletRequest request = (HttpServletRequest)mock.proxy();

          ???????

          ??????? // 調用 HttpServletRequest 對象的方法

          ??????? request.getParameter("name");???????

          ???????

          ??????? // 驗證執行結果

          ??????? mock.verify();

          ??? }

          }

          編譯并將其當做一個 Test Case 運行,會發現兩個測試方法均測試成功。

          例子二

          MyClass 需要測試的類,提供了兩個方法 getName getPassword ,都使用 HttpServletRequest 作為輸入參數并返回從 HttpServletRequest 中取得的參數,具體代碼如下:

          package test2;

          ?

          import javax.servlet.http.*;

          ?

          public class MyClass {

          ??? public String getName(HttpServletRequest request) {

          ?????? return request.getParameter("name");

          ??? }

          ???

          ??? public String getPassword(HttpServletRequest request) {

          ?????? return request.getParameter("password");

          ??? }

          }

          TestMyClass 測試類,其中構造了一個假的 HttpServletRequest 對象,用來測試 MyClass 中的 getName getPassword 方法,代碼如下:

          package test2;

          ?

          import org.jmock.*;

          import javax.servlet.http.*;

          ?

          public class TestMyClass extends MockObjectTestCase{

          ??? private MyClass myclass ;

          ??? private Mock mockRequest ;

          ??? private HttpServletRequest request ;

          ???

          ??? public void setUp() {??????

          ?????? myclass = new MyClass();

          ??????

          ?????? // 構造一個 Mock 對象

          ?????? mockRequest = new Mock(HttpServletRequest.class);

          ??????

          ?????? // 根據 Mock 對象獲取一個 HttpServletRequest 對象

          ?????? request = (HttpServletRequest)mockRequest.proxy();

          ??? }

          ??? public void tearDown() {

          ?????? //TODO

          ??? }

          ??? public void testGetName(){

          ?????? // 設置要執行的操作,以下設置表示要調用一次 HttpServletRequest 對象的

          ??????? //getParameter 方法,傳遞的參數是 "name", 期望的返回是 "kongxx"?????

          ?????? mockRequest.expects(atLeastOnce()).method("getParameter").with(eq("name")).will(returnValue("kongxx"));

          ??????

          ?????? assertNotNull(myclass.getName(request));

          ??????? assertEquals("kongxx" ,myclass.getName(request));??????

          ??? }

          ??? public void testGetPassword(){

          ?????? // 設置要執行的操作,以下設置表示要調用一次 HttpServletRequest 對象的

          ??????? //getParameter 方法,傳遞的參數是 "password", 期望的返回是 "123456789" ?

          ??? ??? mockRequest.expects(atLeastOnce()).method("getParameter").with(eq("password")).will(returnValue("123456789"));

          ??????

          ?????? assertNotNull(myclass.getPassword(request));

          ??????? assertEquals("123456789" ,myclass.getPassword(request));

          ??? }

          }

          編譯并將其當做一個 Test Case 運行,會發現兩個測試方法均測試成功。

          ?

          EasyMock

          簡介

          請訪問 http://www.easymock.org

          準備

          1. ??????? 獲取 J2SDK

          2. ??????? 獲取 JUnit V3.8.1 (從 http://www.junit.org 獲取開發包);

          3. ??????? 獲取 EasyMock V1.1 (從 http://www.easymock.org 獲取 EasyMock 開發包)。

          4. ??????? 為了開發方便,建議使用一個好 IDE 。以下例子中的代碼均是在 Eclipse V3.0 環境下進行的調試。

          例子一

          以下是一個簡單例子,為了方便對比,這里重新實現了 JMock 例子一 ,代碼如下:

          package test1;

          ?

          import org.easymock.*;

          import junit.framework.*;

          import javax.servlet.http.*;

          ?

          public class MockRequestTest extends TestCase{

          ??? private MockControl control;

          ??? private HttpServletRequest mockRequest;

          ?

          ??? public void testMockRequest(){

          ?????? // 創建一個 Mock HttpServletRequest MockControl 對象

          ?????? control = MockControl.createControl(HttpServletRequest.class);

          ??????

          ?????? // 獲取一個 Mock HttpServletRequest 對象

          ?????? mockRequest = (HttpServletRequest) control.getMock();

          ??????????

          ?????? // 設置期望調用的 Mock HttpServletRequest 對象的方法

          ?????? mockRequest.getParameter("name");

          ??????

          ?????? // 設置調用方法期望的返回值,并指定調用次數

          ?????? // 以下后兩個參數表示最少調用一次,最多調用一次

          ?????? control.setReturnValue("kongxx" ,1 ,1);??

          ??????

          ?????? // 設置 Mock HttpServletRequest 的狀態,

          ?????? // 表示此 Mock HttpServletRequest 對象可以被使用

          ?????? control.replay();

          ??????

          ?????? // 使用斷言檢查調用

          ?????? assertEquals("kongxx",mockRequest.getParameter("name"));

          ??????

          ?????? // 驗證期望的調用

          ?????? control.verify();

          ??? }

          }

          編譯并將其當做一個 Test Case 運行,會發現兩個測試方法均測試成功。

          例子二

          同例子一樣,對 JMock 例子二 重新實現產生了 EasyMock 的例子二。

          需要測試的類代碼如下:

          package test2;

          ?

          import javax.servlet.http.*;

          ?

          public class MyClass {

          ??? public String getName(HttpServletRequest request) {

          ?????? return request.getParameter("name");

          ??? }

          ???

          ??? public String getPassword(HttpServletRequest request) {

          ?????? return request.getParameter("password");

          ??? }

          }

          測試類代碼如下:

          package test2;

          ?

          import org.easymock.*;

          import junit.framework.*;

          import javax.servlet.http.*;

          ?

          public class TestMyClass extends TestCase{

          ???

          ??? private MockControl control;

          ??? private HttpServletRequest mockRequest;

          ??? private MyClass myclass ;

          ???

          ??? public void setUp() {??????

          ?????? myclass = new MyClass();

          ??????

          ?????? // 創建一個 Mock HttpServletRequest MockControl 對象

          ?????? control = MockControl.createControl(HttpServletRequest.class);

          ??????

          ?????? // 獲取一個 Mock HttpServletRequest 對象

          ?????? mockRequest = (HttpServletRequest) control.getMock();??????

          ??? }

          ??? public void tearDown() {

          ?????? //TODO

          ??? }

          ??? public void testGetName(){

          ?????? // 設置期望調用的 Mock HttpServletRequest 對象的方法

          ?????? mockRequest.getParameter("name");

          ??????

          ?????? // 設置調用方法期望的返回值,并指定調用次數

          ?????? // 以下后兩個參數表示最少調用一次,最多調用一次

          ?????? control.setReturnValue("kongxx" ,1 ,2);??

          ??????

          ?????? // 設置 Mock HttpServletRequest 的狀態,

          ?????? // 表示此 Mock HttpServletRequest 對象可以被使用

          ?????? control.replay();

          ??????

          ?????? // 使用斷言檢查調用

          ?????? assertNotNull(myclass.getName(mockRequest));

          ?????? assertEquals("kongxx",myclass.getName(mockRequest));

          ??????

          ?????? // 驗證期望的調用

          ?????? control.verify();???

          ??? }

          ??? public void testGetPassword(){

          ?????? // 設置期望調用的 Mock HttpServletRequest 對象的方法

          ?????? mockRequest.getParameter("password");

          ??????

          ?????? // 設置調用方法期望的返回值,并指定調用次數

          ?????? // 以下后兩個參數表示最少調用一次,最多調用一次

          ?????? control.setReturnValue("kongxx" ,1,2);

          ??????

          ?????? // 設置 Mock HttpServletRequest 的狀態,

          ?????? // 表示此 Mock HttpServletRequest 對象可以被使用

          ?????? control.replay();

          ??????

          ?????? // 使用斷言檢查調用

          ?????? assertNotNull(myclass.getPassword(mockRequest));

          ?????? assertEquals("kongxx",myclass.getPassword(mockRequest));

          ??????

          ?????? // 驗證期望的調用

          ?????? control.verify();??

          ??? }

          }

          編譯并將其當做一個 Test Case 運行,會發現兩個測試方法均測試成功。


          獨立測試就是單獨測試一個類或方法里的代碼,而不測試里面調用的其他類或方法的代碼。即假定調用的其他類或方法都正常執行。

        1. 使用Mock Object的場合
          1. 實際對象的行為還不確定。
          2. 實際的對象創建和初始化非常復雜。
          3. 實際對象中存在很難執行到的行為(如網絡異常等)。
          4. 實際的對象運行起來非常的慢。
          5. 實際對象是用戶界面程序。
          6. 實際對象還沒有編寫,只有接口等。
        2. 簡單分析用Mock Object的原因

          假定我們有對象A,它內部頻繁調用了B中的方法。但是除了調用B的部分還存在自己的邏輯代碼。這時,我們只想寫A的單體測試,而不想測試B(因為B可能還沒編寫,只寫了實現的接口或者B運行太慢了影響我們的測試效率)。這樣的話,我們就需要創建B的Mock對象。

          換言之,我們現在不關心B,我們假定B的行為都能正常運行。我們的目標是假定B運行正常的情況下,來對A進行單體測試。

          Mock對象就是我們先不用關心的對象,但是我們的關注對象對它有調用,所以我們給關注對象準備個假貨讓它用。

          ?

        3. posted on 2006-02-17 09:02 扭轉乾坤 閱讀(552) 評論(0)  編輯  收藏 所屬分類: Struts相關

          <2025年8月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          導航

          統計

          常用鏈接

          留言簿(2)

          隨筆分類(31)

          隨筆檔案(30)

          文章分類(32)

          文章檔案(33)

          相冊

          PHP小站-首頁

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 遂川县| 东乡县| 合肥市| 玉树县| 安庆市| 康乐县| 竹山县| 云林县| 邳州市| 垫江县| 家居| 休宁县| 鄄城县| 张家界市| 德阳市| 镇康县| 梁河县| 洪江市| 广宁县| 南城县| 图们市| 肇源县| 伊通| 邓州市| 长岭县| 德格县| 南召县| 新和县| 惠东县| 观塘区| 中山市| 昌黎县| 定远县| 革吉县| 松江区| 玉山县| 新兴县| 马尔康县| 白水县| 贵阳市| 安西县|