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

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

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

    Sky's blog

    我和我追逐的夢

    常用鏈接

    統(tǒng)計(jì)

    其他鏈接

    友情鏈接

    最新評論

    easymock教程-partial class mocking

        easymock中提供對于類的mock功能,我們可以方便的mock這個類的某些方法,指定預(yù)期的行為以便測試這個類的調(diào)用者。這種場景下被mock的類在測試案例中扮演的是次要測試對象或者說依賴的角色,主要測試對象是這個mock類的調(diào)用者。但是有時候我們需要將這個測試類作為主要測試對象,我們希望這個類中的部分(通常是大部分)方法保持原有的正常行為,只有個別方法被我們mock掉以便測試。

    1. 使用方法

        我們先來看看這個partial class mocking 是如何工作的:

        public class Service {

            
    public void execute() {
                actualMethod();
                needMockMethod();
            }


            
    void actualMethod() {
                System.out.println(
    "call actualMethod()");
            }


            
    public void needMockMethod() {
                System.out.println(
    "call needMockMethod()");
            }


        }

        我們給出了一個非常簡單的類,我們將要測試execute()方法,期望能測試到actualMethod()這個方法的正常行為,然后需要mock掉needMockMethod().

    public class PartialClassMockTest extends Assert {

        @Test
        
    public void testPartialMock() {
            Service service 
    = EasyMock.createMockBuilder(Service.class).addMockedMethod("needMockMethod").createMock();
            service.needMockMethod();
            EasyMock.expectLastCall();

            EasyMock.replay(service);
            service.execute();
            EasyMock.verify(service);
        }

    }

        上面的測試案例運(yùn)行通過,輸出為"call actualMethod()",沒有"call needMockMethod()",說明我們設(shè)置的mock生效了。我們創(chuàng)建的mock類的確是只有部分我們制定的方法是mock的,其他都是正常行為。

        再來看看為什么我們要需要partial class mocking 這個功能?為什么需要mock掉其中的一個方法?

        我們來看看下面這個更加真實(shí)的例子:

       public class Service {

            
    public String execute2() {
                
    return getConfiguration();
            }


            
    public String getConfiguration() {
                
    return Configuration.getUsername();
            }

        }


        
    public class Configuration {
            
    public static String getUsername() {
                
    //ignore the code to get configuration from file or database
                return "username";
            }

        }

        這里例子中,需要測試的 execute2()方法需要調(diào)用getConfiguration()方法,而getConfiguration()方法則調(diào)用了Configuration的靜態(tài)方法來獲取配置信息。我們假設(shè)讀取配置的代碼比較復(fù)雜不能直接在單元測試環(huán)境下運(yùn)行,因此通過情況下這里的execute2()方法就會因?yàn)檫@個getConfiguration()而造成無法測試。因此我們可以考慮通過partial class mocking的功能來mock掉getConfiguration()方法從而使得我們的測試案例可以覆蓋到execute2()方法

        @Test
        
    public void testStaticMethod() {
            Service service 
    = EasyMock.createMockBuilder(Service.class).addMockedMethod("getConfiguration").createMock();
            EasyMock.expect(service.getConfiguration()).andReturn(
    "abc");

            EasyMock.replay(service);
            assertEquals(
    "abc", service.execute2());
            EasyMock.verify(service);
        }

        這個測試案例可以正常通過,我們通過partial class mocking成功的避開了getConfiguration()這個絆腳石。

        當(dāng)然這里的實(shí)例代碼本身就有點(diǎn)問題,應(yīng)該采用DI的方法將configuration注入進(jìn)來,而不是在內(nèi)部通過靜態(tài)方法來獲取。因此一個建議是在使用partial class mocking功能前,先看看是不是可以通過重構(gòu)來顯改進(jìn)測試類。只有當(dāng)我們有足夠充分的不得已的理由時,才使用partial class mocking這種變通(或者說取巧)的方式來解決問題。

       
    2. 限制

        上面兩個例子中,我們仔細(xì)看看會發(fā)現(xiàn),被mock的方法都是public的。我們試著將方法修改為protected和default,partial class mocking依然生效。但是修改為private之后,則拋出異常:

    java.lang.IllegalArgumentException: Method not found (or private): needMockMethod
     at org.easymock.internal.MockBuilder.addMockedMethod(MockBuilder.java:75)
     at net.sourcesky.study.easymock.tutorial.PartialClassMockTest.testPartialMock(PartialClassMockTest.java:52)

        或者將mock的方法繼續(xù)保持public,但是加上final,則拋出以下異常:

    java.lang.IllegalStateException: no last call on a mock available
     at org.easymock.EasyMock.getControlForLastCall(EasyMock.java:521)
     at org.easymock.EasyMock.expectLastCall(EasyMock.java:512)
     at net.sourcesky.study.easymock.tutorial.PartialClassMockTest.testPartialMock(PartialClassMockTest.java:54)

        我們回到之前的章節(jié),class mocking里面講述了class mocking的一些限制:private方法和final方法是不能mock的。partial class mocking下這些限制依然存在。因此,為了開啟partial class mocking,我們不得不稍微破壞一下類的封裝原則,對于原本應(yīng)該是private的方法,修改為protected或者default。

        不得不再次申明,partial class mocking不是一個足夠好的解決方案,它只適合在不得已的情況下使用,不要太依賴這個特性。重構(gòu)代碼改善代碼才是王道。

    3. 疑問

        另外class mocking中還講到,對于類的equals(), toString()和hashCode()這三個方法,class mocking下是easymock為這三個方法內(nèi)建了easymock的實(shí)現(xiàn),因此也不能mock。而partial class mocking,這三個方法同樣不能mock,但是easymock不再為它們內(nèi)建實(shí)現(xiàn),而是使用它們正常的功能。

        關(guān)于這點(diǎn)還是有一點(diǎn)疑問,我在easymock的官方文檔中看到以下描述

    Remark: EasyMock provides a default behavior for Object's methods (equals, hashCode, toString). However, for a partial mock, if these methods are not mocked explicitly, they will have their normal behavior instead of EasyMock default's one.

        言下之意,似乎equals, hashCode, toString這三個方法還是可以顯式mock的。但是我測試了一下:

        public class Service {

            
    public String execute3() {
                actualMethod();
                
    return toString();
            }


            @Override
            
    public String toString() {
                
    return "defaultToString()";
            }

        }


        @Test
        
    public void testToStringMethod() {
            Service service 
    = EasyMock.createMockBuilder(Service.class).addMockedMethod("toString").createMock();
            EasyMock.expect(service.toString()).andReturn(
    "abc");
            EasyMock.replay(service);
            assertEquals(
    "abc", service.execute3());
            EasyMock.verify(service);
        }

        toString()方法的mock沒能生效,拋出異常:

    java.lang.IllegalStateException: no last call on a mock available
     at org.easymock.EasyMock.getControlForLastCall(EasyMock.java:521)
     at org.easymock.EasyMock.expect(EasyMock.java:499)
     at net.sourcesky.study.easymock.tutorial.PartialClassMockTest.testToStringMethod(PartialClassMockTest.java:74)

        可以看到明顯是EasyMock.expect(service.toString()).andReturn("abc"); 這里的record沒有成功。

    posted on 2010-11-30 14:23 sky ao 閱讀(3125) 評論(0)  編輯  收藏 所屬分類: software test

    主站蜘蛛池模板: 中文字幕在线免费播放| 黄页网站免费在线观看| 久久亚洲精品成人无码网站| AV大片在线无码永久免费| 亚洲av日韩精品久久久久久a| 国产成人精品曰本亚洲79ren| 免费A级毛片无码A∨中文字幕下载| 亚洲综合色丁香婷婷六月图片| 亚洲国产香蕉人人爽成AV片久久 | 亚洲综合激情视频| 精品剧情v国产在免费线观看| 免费无码av片在线观看| 亚洲国产日韩精品| 国产AV无码专区亚洲AV毛网站| AV片在线观看免费| a毛片全部播放免费视频完整18| 亚洲乱人伦中文字幕无码| 国产精品亚洲片在线| 午夜男人一级毛片免费 | 国产免费av片在线无码免费看| 精品四虎免费观看国产高清午夜| 国产亚洲精品VA片在线播放| 久久久久久久综合日本亚洲 | 亚洲国产精品成人| 国产成人精品免费午夜app| selaoban在线视频免费精品| 亚洲日本乱码卡2卡3卡新区| 国产∨亚洲V天堂无码久久久| 在线观看免费亚洲| 亚洲第一成年免费网站| 成在人线av无码免费高潮喷水| 国产亚洲视频在线观看网址| 亚洲免费中文字幕| 亚洲AV日韩AV高潮无码专区| 亚洲国产一成久久精品国产成人综合 | 拔擦拔擦8x华人免费久久| 91久久青青草原线免费| 久久成人18免费网站 | 成年网站免费视频A在线双飞| 成全视频在线观看免费| 白白色免费在线视频|