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

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

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

    ALL is Well!

    敏捷是一條很長的路,摸索著前進(jìn)著

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      30 隨筆 :: 23 文章 :: 71 評論 :: 0 Trackbacks

    jMock用法簡介

    總體上來說,jMock 是一個(gè)輕量級的模擬對象技術(shù)的實(shí)現(xiàn)。它具有以下特點(diǎn):
    1.可以用簡單易行的方法定義模擬對象,無需破壞本來的代碼結(jié)構(gòu)表;
    2.可以定義對象之間的交互,從而增強(qiáng)測試的穩(wěn)定性;
    3.可以集成到測試框架;
    4.易擴(kuò)充;

    使用 jMock 模擬對象

    我們首先必須引入 jMock 的類,定義我們的測試類,創(chuàng)建一個(gè) Mockery 的對象用來代表上下文。上下文可以模擬出對象和對象的輸出,并且還可以檢測應(yīng)用是否合法。

     

    @SuppressWarnings("unchecked")
    public class BookListTest {
        
    private final Mockery context = new JUnit4Mockery() {
            
    {
                
    // 聲明針對類進(jìn)行mock,針對接口則會采用動態(tài)代理,不需要聲明
                setImposteriser(ClassImposteriser.INSTANCE);
            }

        }
    ;
    }


    context 對象便可以用來創(chuàng)建Mock對象。
    接下來的例子,我們模擬一個(gè)ServiceCall對象,我們以它的Map call(String target, Map dataMap)為例,針對此方法,設(shè)定預(yù)期值。然后我們在執(zhí)行用例的時(shí)候調(diào)用此方法,便可以得到預(yù)期值。

    @SuppressWarnings("unchecked")
    public class BookListTest {
        
    private final Mockery context = new JUnit4Mockery() {
            
    {
                setImposteriser(ClassImposteriser.INSTANCE);
            }

        }
    ;

        @Test
        
    public void testExecuteNormal() throws Exception {
            
    final ServiceCall sCall = context.mock(ServiceCall.class);
            context.checking(
    new Expectations() {
                
    {
                    one(sCall).call(JMockService.queryDtlInfo, 
    null);
                    
    // 構(gòu)建預(yù)期結(jié)果
                    Map ret = new HashMap();
                    ret.put(
    "OrderId""9800000000");
                    ret.put(
    "Data"new ArrayList());
                    
    // 設(shè)定預(yù)期值
                    will(returnValue(ret));
                    
                    
    // 第二次被調(diào)用時(shí),返回null
                    one(sCall).call(JMockService.queryDtlInfo, new HashMap());
                    will(returnValue(
    null));
                }

            }
    );

            BookList bListAction 
    = new BookList();
            bListAction.setName(
    "jnbzwm");
            
    // 設(shè)定ServiceCall對象為Mock對象
            bListAction.setServiceCall(sCall);

            
    // 執(zhí)行Action方法
            bListAction.execute();

            Assert.assertEquals(
    "9800000000", bListAction.getOrderId());
            Assert.assertEquals(
    0, bListAction.getDataList().size());
        }



    校驗(yàn)expectations中的規(guī)則

    使用jMock時(shí),一般會通過如下代碼指定expectations:

    private final Mockery context = new JUnit4Mockery() {
            
    {
                setImposteriser(ClassImposteriser.INSTANCE);
            }

        }
    ;

        @Test
        
    public void testExecuteNormal() throws Exception {
            
    final ServiceCall sCall = context.mock(ServiceCall.class);
            context.checking(
    new Expectations() {
                
    {
                    one(sCall).call(JMockService.queryDtlInfo, 
    null);
                    
    // 構(gòu)建預(yù)期結(jié)果
                    Map ret = new HashMap();
                    ret.put(
    "OrderId""9800000000");
                    ret.put(
    "Data"new ArrayList());
                    
    // 設(shè)定預(yù)期值
                    will(returnValue(ret));
                    
                    
    // 第二次被調(diào)用時(shí),返回null
                    one(sCall).call(JMockService.queryDtlInfo, new HashMap());
                    will(returnValue(
    null));
                }

            }
    );
            .
        }

    }

    為了校驗(yàn)expectations中的規(guī)則是否都滿足,可以在測試完成后通過增加 context.assertIsSatisfied()方法來驗(yàn)證expectations是否滿足。
    如下代碼:

        @Test
        
    public void testExecuteNormal() throws Exception {
            
    final ServiceCall sCall = context.mock(ServiceCall.class);
            context.checking(
    new Expectations() {
                
    {
                    one(sCall).call(JMockService.queryDtlInfo, 
    null);
                    
    // 構(gòu)建預(yù)期結(jié)果
                    Map ret = new HashMap();
                    ret.put(
    "OrderId""9800000000");
                    ret.put(
    "Data"new ArrayList());
                    
    // 設(shè)定預(yù)期值
                    will(returnValue(ret));
                    
                    
    // 第二次被調(diào)用時(shí),返回null
                    one(sCall).call(JMockService.queryDtlInfo, new HashMap());
                    will(returnValue(
    null));
                }

            }
    );

            BookList bListAction 
    = new BookList();
            bListAction.setName(
    "jnbzwm");
            
    // 設(shè)定ServiceCall對象為Mock對象
            bListAction.setUpfServiceCall(sCall);

            
    // 執(zhí)行Action方法
            bListAction.execute();

            Assert.assertEquals(
    "9800000000", bListAction.getOrderId());
            Assert.assertEquals(
    0, bListAction.getDataList().size());
            context.assertIsSatisfied(); 
        }

    由于我定義了兩條規(guī)則,而第二條并未調(diào)用,所以此用例不會通過。

    同一個(gè)方法連續(xù)調(diào)用時(shí)返回不同的值

    有兩種方法,第一種就是直接通過多次調(diào)用 will(returnValue(X))來指定。如:

        @Test
        
    public void testExecuteNormal() throws Exception {
            
    final ServiceCall sCall = context.mock(ServiceCall.class);
            context.checking(
    new Expectations() {
                
    {
                    one(sCall).call(JMockService.queryDtlInfo, 
    null);
                    will(returnValue(
    0));

                    
    // 第二次被調(diào)用時(shí),返回1
                    one(sCall).call(JMockService.queryDtlInfo, null);
                    will(returnValue(
    1));

                    
    // 第三次被調(diào)用時(shí),返回2
                    one(sCall).call(JMockService.queryDtlInfo, null);
                    will(returnValue(
    2));
                }

            }
    );
            
        }

    然而第一種方法會增加維護(hù)成本,且缺乏可控性。jMock提供了第二種方法,即通過onConsecutiveCalls的action來實(shí)現(xiàn)返回不同的返回值。如:

     

        @Test
        
    public void testExecuteNormal() throws Exception {
            
    final ServiceCall sCall = context.mock(ServiceCall.class);
            context.checking(
    new Expectations() {
                
    {
                    atLeast(
    1).of (sCall).call(JMockService.queryDtlInfo, null);
                    will(onConsecutiveCalls( returnValue(
    0),  returnValue(1),  returnValue(2))); 
                }

            }
    );
            
        }



    指定mock的方法拋出異常

    在will方法中直接使用throwException的action。參考如下語法:

    one(sCall).call(JMockService.queryDtlInfo, null);
    // 設(shè)定預(yù)期值,拋出異常
    will(throwException(new BusinessException("~", "name can't empty.")));
    

    結(jié)合測試異常一起使用,代碼如下:

        @Test(expected=BusinessException.class)
        
    public void testExecuteNormal() throws Exception {
            
    final ServiceCall sCall = context.mock(ServiceCall.class);
            context.checking(
    new Expectations() {
                
    {
                    one(sCall).call(JMockService.queryDtlInfo, 
    null);
                    
    // 構(gòu)建預(yù)期結(jié)果
                    Map ret = new HashMap();
                    ret.put(
    "OrderId""9800000000");
                    ret.put(
    "Data"new ArrayList());
                    
    // 設(shè)定預(yù)期值
                    will(throwException(new BusinessException("~""name can't empty.")));

                    
    // 第二次被調(diào)用時(shí),返回null
                    one(sCall).call(JMockService.queryDtlInfo, new HashMap());
                    will(returnValue(
    null));
                }

            }
    );

            BookList bListAction 
    = new BookList();
            bListAction.setName(
    "");
            
    // 設(shè)定ServiceCall對象為Mock對象
            bListAction.setUpfServiceCall(sCall);

            
    // 執(zhí)行Action方法
            bListAction.execute();
        }


    posted on 2010-12-17 09:28 李 明 閱讀(12095) 評論(3)  編輯  收藏 所屬分類: JUnit

    評論

    # Nike Air Jordan 2010-12-17 10:16 Nike Air Jordan
    看得迷迷糊糊的  回復(fù)  更多評論
      

    # re: JUnit單元測試Mock技術(shù)之jMock用法介紹 2010-12-17 10:59 Ronaldo
    @Nike Air Jordan
    怎么迷糊了?  回復(fù)  更多評論
      

    # re: JUnit單元測試Mock技術(shù)之jMock用法介紹 2016-07-18 15:14 pjl
    JMockService是啥?  回復(fù)  更多評論
      


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


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 国产成人无码区免费网站| 最近最新高清免费中文字幕| 亚洲成av人片在线看片| 亚洲熟妇丰满多毛XXXX| 日韩免费视频网站| 国产一精品一AV一免费孕妇| 久久久高清日本道免费观看| 亚洲另类无码专区丝袜| 亚洲最大黄色网址| 亚洲美女精品视频| 亚洲人成电影在线天堂| 亚洲成AV人片在线观看WWW| 国产精品亚洲高清一区二区 | 久久一区二区三区免费| 日日躁狠狠躁狠狠爱免费视频| 亚洲乱理伦片在线观看中字| 亚洲熟妇AV日韩熟妇在线| 日韩亚洲国产综合高清| 亚洲欧美日韩中文无线码| 在线亚洲午夜片AV大片| 亚洲Av永久无码精品黑人| 国产精品亚洲一区二区无码 | www.亚洲一区| 91麻豆精品国产自产在线观看亚洲| 久久久久亚洲精品中文字幕| 亚洲人成电影网站国产精品| 国产午夜亚洲精品国产成人小说| 亚洲免费在线观看| 亚洲国产成人片在线观看无码| 亚洲国产另类久久久精品小说| 国产精品亚洲一区二区三区在线| 久久亚洲精品中文字幕| 在线综合亚洲中文精品| 国产精品久久亚洲一区二区| 在线免费视频你懂的| 8888四色奇米在线观看免费看| 免费在线看v网址| 日韩一级视频免费观看| 色噜噜亚洲精品中文字幕 | 亚洲日韩在线视频| 久久久久久亚洲精品无码|