<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    我的漫漫程序之旅

    專注于JavaWeb開發(fā)
    隨筆 - 39, 文章 - 310, 評(píng)論 - 411, 引用 - 0
    數(shù)據(jù)加載中……

    EasyMock使用手記

    Mock 對(duì)象能夠模擬領(lǐng)域?qū)ο蟮牟糠中袨椋⑶夷軌驒z驗(yàn)運(yùn)行結(jié)果是否和預(yù)期的一致。領(lǐng)域類將通過與 Mock 對(duì)象的交互,來獲得一個(gè)獨(dú)立的測(cè)試環(huán)境(引自《 精通 Spring——Java 輕量級(jí)架構(gòu)開發(fā)實(shí)踐 》。

    在模仿對(duì)象中,我們定義了四個(gè)概念:

    1 )目標(biāo)對(duì)象:正在測(cè)試的對(duì)象

    2 )合作者對(duì)象:由目標(biāo)對(duì)象創(chuàng)建或獲取的對(duì)象

    3 )模仿對(duì)象:遵循模仿對(duì)象模式的合作者的子類(或?qū)崿F(xiàn))

    4 )特殊化對(duì)象:覆蓋創(chuàng)建方法以返回模仿對(duì)象而不是合作者的目標(biāo)的子類

    一般來說,應(yīng)用模仿對(duì)象的過程如下:

    1 )創(chuàng)建模仿對(duì)象的實(shí)例

    2 )設(shè)置模仿對(duì)象中的狀態(tài)和期望值

    3 )將模仿對(duì)象作為參數(shù)來調(diào)用域代碼

    4 )驗(yàn)證模仿對(duì)象中的一致性

    那么,我們應(yīng)該如何以及在哪里使用 Mock 對(duì)象呢?一般來說,對(duì)于目標(biāo)對(duì)象中的合作者對(duì)象,在測(cè)試時(shí)如果其狀態(tài)或行為的實(shí)現(xiàn)嚴(yán)重地依賴外部資源(比如數(shù)據(jù)持久化中的 DAO ,比如負(fù)責(zé)發(fā)送電子郵件的類),或者團(tuán)隊(duì)并行開發(fā)時(shí),目標(biāo)對(duì)象的合作者對(duì)象并沒有實(shí)現(xiàn)(比如 J2EE 中,橫向分工時(shí),負(fù)責(zé) Action 的調(diào)用 Service ,負(fù)責(zé) Service 調(diào)用 DAO 時(shí),相應(yīng)的 Service DAO 沒有實(shí)現(xiàn)),這時(shí)我們就需要模仿這些類。其實(shí),在做 J2EE 時(shí),傳統(tǒng)的 N 層架構(gòu)中,我們都是面向接口編程的,我們定義了 DAO 接口,我們定義了 Service 接口,這樣做的優(yōu)點(diǎn)就是我們?cè)跍y(cè)試時(shí)可以構(gòu)造實(shí)現(xiàn)接口的 Mock 類。這里不得不提依賴注入,通過依賴注入,我們才能在測(cè)試時(shí) set Mock 對(duì)象。這也說明,為了方便測(cè)試,我們不得不一步一步 重構(gòu)代碼,而模式就在重構(gòu)中自然地產(chǎn)生了。

    對(duì)于 Mock 對(duì)象,我們可以根據(jù) 合作者接口(或者是類) 實(shí)現(xiàn)具體的 Mock 類,這樣的 Mock 類實(shí)際上是 Stub 。有些情況下, Stub 是必要的。但對(duì)于諸如 DAO Service ,我們只關(guān)心在給定參數(shù)的情況下,調(diào)用的方法能夠返回預(yù)期的值,我們根本不關(guān)心其內(nèi)部實(shí)現(xiàn),這時(shí)候如果使用 Stub 的話就會(huì)產(chǎn)生不必要的代碼。我們需要的就是能 動(dòng)態(tài)地生成 Mock 對(duì)象而不需要編寫它們的工具, EasyMock 就是這樣的工具。

    EasyMock 是一個(gè) Mock 對(duì)象的類庫,現(xiàn)在的版本是 2.0 ,這個(gè)版本只支持 Mock 接口,如果需要 Mock 類,需要下載它的擴(kuò)展包。

    下面通過一個(gè)具體的例子說明一下 Mock 對(duì)象的使用,我寫的例子就是測(cè)試 Service 類中的一個(gè)方法, Mock 的對(duì)象是 DAO

    首先是一個(gè)簡單的實(shí)體 bean Account:

    package  easymocktest.domain;

    import
     org.apache.commons.lang.builder.ToStringBuilder;
    import
     org.apache.commons.lang.builder.ToStringStyle;

    public   class  Account  {

        
    private  Long id;
        
    private  String name;
        
    private  String pwd;
        
        
    public  Long getId()  {
            
    return  id;
        }

        
    public   void  setId(Long id)  {
            
    this .id  =  id;
        }

        
    public  String getName()  {
            
    return  name;
        }

        
    public   void  setName(String name)  {
            
    this .name  =  name;
        }

        
    public  String getPwd()  {
            
    return  pwd;
        }

        
    public   void  setPwd(String pwd)  {
            
    this .pwd  =  pwd;
        }

        
    /**
         * 
    @see  java.lang.Object#toString()
         
    */

        
    public  String toString()  {
            
    return   new  ToStringBuilder( this , ToStringStyle.MULTI_LINE_STYLE)
                    .append(
    " name " this .name).append( " pwd " this .pwd).append( " id " ,
                            
    this .id).toString();
        }

        
    }

          

        一個(gè)只含一個(gè)方法的 DAO AccountDAO:

    package  easymocktest.dao;

    import  easymocktest.domain. *
    ;
    public   interface  AccountDAO  {
        
    public  Account getByNameAndPwd(String name,String pwd);
    }

        

     

       一個(gè)同樣只含一個(gè)方法的 AccountService 接口:

     

    package  easymocktest.service;

    import  easymocktest.domain. *
    ;
    public   interface  AccountService  {
        
    public  Account getAccount(String name,String pwd);
    }

       與 AccountService 相應(yīng)的實(shí)現(xiàn)類:

    package  easymocktest.service.impl;

    import
     easymocktest.service.AccountService;
    import  easymocktest.dao. *
    ;
    import
     easymocktest.domain.Account;
    public   class  AccountServiceImpl  implements  AccountService  {

        
    private  AccountDAO accountDAO;

        
    public  AccountDAO getAccountDAO()  {
            
    return  accountDAO;
        }


        
    public   void  setAccountDAO(AccountDAO accountDAO)  {
            
    this .accountDAO  =  accountDAO;
        }


        
    public  Account getAccount(String name, String pwd)  {
            
    return   this .accountDAO.getByNameAndPwd(name, pwd);
        }


    }


       這里我沒有實(shí)現(xiàn) AccountDAO 接口,對(duì)于 Mock 測(cè)試來說,這也是不需要的。下面就是 AccountServiceImpl 的測(cè)試類 AccountServiceTest
       

    package  easymocktest.service;

    import  junit.framework. *
    ;
    import  easymocktest.dao. *
    ;
    import  easymocktest.domain. *
    ;
    import  easymocktest.service.impl. *
    ;
    import   static
     org.easymock.EasyMock.createMock;
    import   static
     org.easymock.EasyMock.replay;
    import   static
     org.easymock.EasyMock.reset;
    import   static
     org.easymock.EasyMock.verify;
    import   static
     org.easymock.EasyMock.expect;
    public   class  AccountServiceTest  extends  TestCase {

        
    private  AccountDAO accountDAOMock;
        
    private  AccountServiceImpl accountService;
        
        @Override
        
    protected   void  setUp()  throws  Exception  {
            accountDAOMock 
    =  createMock(AccountDAO. class );
            accountService 
    =   new  AccountServiceImpl();
            accountService.setAccountDAO(accountDAOMock);
        }

        
        
    public   void  testGetAccount() {
            String name 
    =   " kafka " ;
            String pwd 
    =   " 0102 " ;
            Account a 
    =   new  Account();
            a.setName(name);
            a.setPwd(pwd);
            a.setId(
    new  Long( 10 ));
            reset(accountDAOMock);
    // (a)
            expect(accountDAOMock.getByNameAndPwd(name, pwd)).andReturn(a); // (b)
            replay(accountDAOMock); // (c)
            Account b  =  accountService.getAccount(name, pwd);
            assertEquals(a, b);
            verify(accountDAOMock);
    // (d)
        }

    }

       

    下面簡要的說明一下 Mock 對(duì)象的工作過程:

    1 )在 setUp() 中,通過 “accountDAOMock = createMock(AccountDAO.class);” (這里使用了 java5 中的靜態(tài)導(dǎo)入),創(chuàng)建 AccountDAO Mock 對(duì)象,由于 EasyMock 采用了范型技術(shù),故創(chuàng)建的 Mock 對(duì)象不需要強(qiáng)制類型轉(zhuǎn)換。然后通過 “accountService.setAccountDAO(accountDAOMock);” 設(shè)置目標(biāo)對(duì)象的合作者對(duì)象。

    2 )對(duì)于測(cè)試方法 “testGetAccount()” (a) 處的 reset() 方法是將 Mock 對(duì)象復(fù)位,也就是重新設(shè)置 Mock 對(duì)象的狀態(tài)和行為。由于此處是第一次調(diào)用 Mock 對(duì)象,可以不必使用 reset() 方法。

    3 (b) expect() 是錄制 Mock 對(duì)象方法的調(diào)用,其參數(shù)就是 Mock 對(duì)象的方法,其中如果調(diào)用的方法有返回值,要通過 andReturn() 方法設(shè)置預(yù)期的返回值。

    4 (c) 處的 replay() 是結(jié)束錄制過程。 在調(diào)用 replay() 方法之前的狀態(tài), EashMock 稱之為 “record 狀態(tài)。該狀態(tài)下, Mock 對(duì)象不具備行為(即模擬接口的實(shí)現(xiàn)),它僅僅記錄方法的調(diào)用。在調(diào)用 replay() 后,它才以 Mock 對(duì)象預(yù)期的行為進(jìn)行工作,檢查預(yù)期的方法調(diào)用是否真的完成。

    5 (d) 處的 verify() 是用于在錄制和回放兩個(gè)步驟完成之后進(jìn)行預(yù)期和實(shí)際結(jié)果的檢查。這里就是檢查 accountDAOMock 是否如預(yù)期一樣調(diào)用了 getByNameAndPwd 方法。

     

    對(duì)于上面的舉例,它可能并不具有實(shí)際的價(jià)值,這里我只想拋磚引玉。在 N 層架構(gòu)的 Java 程序中, Mock 對(duì)象在單元測(cè)試中正發(fā)揮著越來越重要的作用。我現(xiàn)在看到的是,在 Service 層與 Web 層, Mock 對(duì)象能很好的被應(yīng)用。有人覺得在 Persistence 層也應(yīng)該使用 Mock 對(duì)象,但就像我們所知道的,在使用 Hibernate Ibatis ORM 工具的情況下,我們的 Persistence 層的測(cè)試主要測(cè)試的就是那些配置文件、查詢語句等(實(shí)際上是集成測(cè)試),如果還 Mock 的話,就失去了測(cè)試的意義。

       對(duì)于 Mock 的更多的信息,你可以訪問Mock Objects,在本文寫作的過程中,參考了使用模仿對(duì)象進(jìn)行單元測(cè)試

    等文章,一并感謝。



    posted on 2007-11-24 07:22 々上善若水々 閱讀(1724) 評(píng)論(0)  編輯  收藏 所屬分類: 軟件測(cè)試

    主站蜘蛛池模板: 亚洲午夜在线电影| 免费A级毛片无码视频| 国产成人亚洲合集青青草原精品| 亚洲国产电影av在线网址| 韩国免费一级成人毛片| 国内精品免费视频精选在线观看| 色天使亚洲综合一区二区| 精品亚洲国产成人| 亚洲视频在线免费播放| 亚洲日韩精品无码专区网址| 免费一级毛片女人图片| 免费无遮挡无码视频网站| 99久久99久久精品免费看蜜桃 | 成年轻人网站色免费看| 日韩精品久久久久久免费| 久久WWW免费人成—看片| 高潮毛片无遮挡高清免费视频| 一本色道久久88—综合亚洲精品| 中文字幕亚洲综合久久| 亚洲AV本道一区二区三区四区| 国产成人亚洲精品狼色在线| 亚洲av午夜精品一区二区三区 | 亚洲视频无码高清在线| 亚洲综合无码一区二区三区| 亚洲精品乱码久久久久久久久久久久 | 一级特黄录像免费播放肥| 尤物视频在线免费观看| 免费亚洲视频在线观看| 亚洲AV无码一区二区三区鸳鸯影院| 亚洲五月综合网色九月色| 亚洲国产日韩在线成人蜜芽| 亚洲人成在线精品| 亚洲人成网站在线播放2019| 一区二区亚洲精品精华液| 亚洲人片在线观看天堂无码| 日本亚洲中午字幕乱码| 深夜福利在线免费观看| 一区二区三区免费视频播放器| 精品多毛少妇人妻AV免费久久| 中文字幕无码毛片免费看| 国产精品视频白浆免费视频|