Struts測(cè)試之Mock Object測(cè)試

          Struts測(cè)試之Mock Object測(cè)試

          以下內(nèi)容引自 http://www.xgdown.com/article/239/47289_1.htm

          使用Mock Object進(jìn)行測(cè)試,主要是用來(lái)模擬那些在應(yīng)用中不容易構(gòu)造(如HttpServletRequest必須在Servlet容器中才能構(gòu)造出來(lái))或者比較復(fù)雜的對(duì)象(如JDBC中的ResultSet對(duì)象)從而使測(cè)試順利進(jìn)行的工具。

          JMock

          簡(jiǎn)介

          請(qǐng)?jiān)L問 http://www.jmock.org 。

          準(zhǔn)備

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

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

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

          4.??????? 為了開發(fā)方便,建議使用一個(gè)好 IDE 。以下例子中的代碼均是在 Eclipse V3.0 環(huán)境下進(jìn)行的調(diào)試。

          例子一

          以下是一個(gè)簡(jiǎn)單例子,代碼如下:

          package test1;

          ?

          import org.jmock.*;

          import javax.servlet.http.*;

          ?

          public class MockRequestTest extends MockObjectTestCase{

          ??? public void testMockRequest1(){

          ?????? // 構(gòu)造一個(gè) Mock 對(duì)象

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

          ???????

          ??????? // 設(shè)置要執(zhí)行的操作,以下設(shè)置表示要調(diào)用一次 HttpServletRequest 對(duì)象的

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

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

          ???????

          ??????? // 根據(jù) Mock 對(duì)象獲取一個(gè) HttpServletRequest 對(duì)象

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

          ???????

          ??????? // 斷言調(diào)用結(jié)果

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

          ??? }

          ??? public void testMockRequest2(){

          ?????? // 構(gòu)造一個(gè) Mock 對(duì)象

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

          ???????

          ??????? // 設(shè)置要執(zhí)行的操作,以下設(shè)置表示要調(diào)用一次 HttpServletRequest 對(duì)象的

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

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

          ???????

          ??????? // 根據(jù) Mock 對(duì)象獲取一個(gè) HttpServletRequest 對(duì)象

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

          ???????

          ??????? // 調(diào)用 HttpServletRequest 對(duì)象的方法

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

          ???????

          ??????? // 驗(yàn)證執(zhí)行結(jié)果

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

          ??? }

          }

          編譯并將其當(dāng)做一個(gè) Test Case 運(yùn)行,會(huì)發(fā)現(xiàn)兩個(gè)測(cè)試方法均測(cè)試成功。

          例子二

          MyClass 需要測(cè)試的類,提供了兩個(gè)方法 getName getPassword ,都使用 HttpServletRequest 作為輸入?yún)?shù)并返回從 HttpServletRequest 中取得的參數(shù),具體代碼如下:

          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 測(cè)試類,其中構(gòu)造了一個(gè)假的 HttpServletRequest 對(duì)象,用來(lái)測(cè)試 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();

          ??????

          ?????? // 構(gòu)造一個(gè) Mock 對(duì)象

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

          ??????

          ?????? // 根據(jù) Mock 對(duì)象獲取一個(gè) HttpServletRequest 對(duì)象

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

          ??? }

          ??? public void tearDown() {

          ?????? //TODO

          ??? }

          ??? public void testGetName(){

          ?????? // 設(shè)置要執(zhí)行的操作,以下設(shè)置表示要調(diào)用一次 HttpServletRequest 對(duì)象的

          ??????? //getParameter 方法,傳遞的參數(shù)是 "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(){

          ?????? // 設(shè)置要執(zhí)行的操作,以下設(shè)置表示要調(diào)用一次 HttpServletRequest 對(duì)象的

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

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

          ??????

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

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

          ??? }

          }

          編譯并將其當(dāng)做一個(gè) Test Case 運(yùn)行,會(huì)發(fā)現(xiàn)兩個(gè)測(cè)試方法均測(cè)試成功。

          ?

          EasyMock

          簡(jiǎn)介

          請(qǐng)?jiān)L問 http://www.easymock.org 。

          準(zhǔn)備

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

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

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

          4. ??????? 為了開發(fā)方便,建議使用一個(gè)好 IDE 。以下例子中的代碼均是在 Eclipse V3.0 環(huán)境下進(jìn)行的調(diào)試。

          例子一

          以下是一個(gè)簡(jiǎn)單例子,為了方便對(duì)比,這里重新實(shí)現(xiàn)了 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(){

          ?????? // 創(chuàng)建一個(gè) Mock HttpServletRequest MockControl 對(duì)象

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

          ??????

          ?????? // 獲取一個(gè) Mock HttpServletRequest 對(duì)象

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

          ??????????

          ?????? // 設(shè)置期望調(diào)用的 Mock HttpServletRequest 對(duì)象的方法

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

          ??????

          ?????? // 設(shè)置調(diào)用方法期望的返回值,并指定調(diào)用次數(shù)

          ?????? // 以下后兩個(gè)參數(shù)表示最少調(diào)用一次,最多調(diào)用一次

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

          ??????

          ?????? // 設(shè)置 Mock HttpServletRequest 的狀態(tài),

          ?????? // 表示此 Mock HttpServletRequest 對(duì)象可以被使用

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

          ??????

          ?????? // 使用斷言檢查調(diào)用

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

          ??????

          ?????? // 驗(yàn)證期望的調(diào)用

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

          ??? }

          }

          編譯并將其當(dāng)做一個(gè) Test Case 運(yùn)行,會(huì)發(fā)現(xiàn)兩個(gè)測(cè)試方法均測(cè)試成功。

          例子二

          同例子一樣,對(duì) JMock 例子二 重新實(shí)現(xiàn)產(chǎn)生了 EasyMock 的例子二。

          需要測(cè)試的類代碼如下:

          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");

          ??? }

          }

          測(cè)試類代碼如下:

          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();

          ??????

          ?????? // 創(chuàng)建一個(gè) Mock HttpServletRequest MockControl 對(duì)象

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

          ??????

          ?????? // 獲取一個(gè) Mock HttpServletRequest 對(duì)象

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

          ??? }

          ??? public void tearDown() {

          ?????? //TODO

          ??? }

          ??? public void testGetName(){

          ?????? // 設(shè)置期望調(diào)用的 Mock HttpServletRequest 對(duì)象的方法

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

          ??????

          ?????? // 設(shè)置調(diào)用方法期望的返回值,并指定調(diào)用次數(shù)

          ?????? // 以下后兩個(gè)參數(shù)表示最少調(diào)用一次,最多調(diào)用一次

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

          ??????

          ?????? // 設(shè)置 Mock HttpServletRequest 的狀態(tài),

          ?????? // 表示此 Mock HttpServletRequest 對(duì)象可以被使用

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

          ??????

          ?????? // 使用斷言檢查調(diào)用

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

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

          ??????

          ?????? // 驗(yàn)證期望的調(diào)用

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

          ??? }

          ??? public void testGetPassword(){

          ?????? // 設(shè)置期望調(diào)用的 Mock HttpServletRequest 對(duì)象的方法

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

          ??????

          ?????? // 設(shè)置調(diào)用方法期望的返回值,并指定調(diào)用次數(shù)

          ?????? // 以下后兩個(gè)參數(shù)表示最少調(diào)用一次,最多調(diào)用一次

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

          ??????

          ?????? // 設(shè)置 Mock HttpServletRequest 的狀態(tài),

          ?????? // 表示此 Mock HttpServletRequest 對(duì)象可以被使用

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

          ??????

          ?????? // 使用斷言檢查調(diào)用

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

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

          ??????

          ?????? // 驗(yàn)證期望的調(diào)用

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

          ??? }

          }

          編譯并將其當(dāng)做一個(gè) Test Case 運(yùn)行,會(huì)發(fā)現(xiàn)兩個(gè)測(cè)試方法均測(cè)試成功。


          獨(dú)立測(cè)試就是單獨(dú)測(cè)試一個(gè)類或方法里的代碼,而不測(cè)試?yán)锩嬲{(diào)用的其他類或方法的代碼。即假定調(diào)用的其他類或方法都正常執(zhí)行。

        1. 使用Mock Object的場(chǎng)合
          1. 實(shí)際對(duì)象的行為還不確定。
          2. 實(shí)際的對(duì)象創(chuàng)建和初始化非常復(fù)雜。
          3. 實(shí)際對(duì)象中存在很難執(zhí)行到的行為(如網(wǎng)絡(luò)異常等)。
          4. 實(shí)際的對(duì)象運(yùn)行起來(lái)非常的慢。
          5. 實(shí)際對(duì)象是用戶界面程序。
          6. 實(shí)際對(duì)象還沒有編寫,只有接口等。
        2. 簡(jiǎn)單分析用Mock Object的原因

          假定我們有對(duì)象A,它內(nèi)部頻繁調(diào)用了B中的方法。但是除了調(diào)用B的部分還存在自己的邏輯代碼。這時(shí),我們只想寫A的單體測(cè)試,而不想測(cè)試B(因?yàn)锽可能還沒編寫,只寫了實(shí)現(xiàn)的接口或者B運(yùn)行太慢了影響我們的測(cè)試效率)。這樣的話,我們就需要?jiǎng)?chuàng)建B的Mock對(duì)象。

          換言之,我們現(xiàn)在不關(guān)心B,我們假定B的行為都能正常運(yùn)行。我們的目標(biāo)是假定B運(yùn)行正常的情況下,來(lái)對(duì)A進(jìn)行單體測(cè)試。

          Mock對(duì)象就是我們先不用關(guān)心的對(duì)象,但是我們的關(guān)注對(duì)象對(duì)它有調(diào)用,所以我們給關(guān)注對(duì)象準(zhǔn)備個(gè)假貨讓它用。

          ?

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


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          <2025年8月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(2)

          隨筆分類(31)

          隨筆檔案(30)

          文章分類(32)

          文章檔案(33)

          相冊(cè)

          PHP小站-首頁(yè)

          搜索

          積分與排名

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 射阳县| 朝阳县| 滕州市| 连平县| 乐山市| 宁海县| 平武县| 文安县| 宣城市| 福安市| 清镇市| 会理县| 泸水县| 景泰县| 西青区| 宁安市| 女性| 玉田县| 邢台县| 格尔木市| 溧水县| 焦作市| 安国市| 白玉县| 金门县| 寿阳县| 南充市| 沛县| 德格县| 奉贤区| 南华县| 繁峙县| 灵川县| 新乐市| 巴林右旗| 无棣县| 电白县| 兴仁县| 米泉市| 潞城市| 星子县|