qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          單元測試中mock的使用及mock神器jmockit實踐

          在最近的r應用的單元測試中,經常需要用到mock,可以說mock在ut (unit test)中是無處不在的。而在r的ut實踐中也找到了一種很簡潔的mock方式,不僅解決了ut中所有需要mock的地方,而且可以很少量的代碼來完成mock。詳見下文。

            一.Mock的使用場景:

            比如以下場景:

            1. mock掉外部依賴的應用的HSF service的調用,比如uic,tp 的hsf服務依賴。

            2. 對DAO層(訪問mysql、oracle、tair、tfs等底層存儲)的調用mock等。

            3. 對系統間異步交互notify消息的mock。

            4. 對method_A里面調用到的method_B 的mock 。

            5. 對一些應用里面自己的 class(abstract, final, static),interface,annotation ,enum,native等的mock。

            二. Mock工具的原理:

            mock工具工作的原理大都如下:

            1. record階段:錄制期望。也可以理解為數據準備階段。創建依賴的class 或interface或method ,模擬返回的數據,及調用的次數等。

            2. replay階段:通過調用被測代碼,執行測試。期間會invoke 到 第一階段record的mock對象或方法。

            3. verify階段:驗證??梢则炞C調用返回是否正確。及mock的方法調用次數,順序等。

            三. 當前的一些Mock工具的比較:

            歷史曾經或當前比較流行的Mock工具有EasyMock、jMock、Mockito、Unitils Mock、PowerMock、jmockit等工具。

            他們的功能對比如下:

            從這里可以看到,當前為什么jmockit為什么這么火爆了!所以我們的UT中的mock工具也選擇了目前無所不能的jmockit。

            而在使用的過程中,感覺到jmockit的 Auto-injection of mocks 及 Special fields for "any" argument matching  及各種有用的 Annotation 給測試代碼精簡和測試效率提升帶來了實實在在的好處。



            四. Jmockit的簡介:

            JMockit 是用以幫助開發人員編寫測試程序的一組工具和API,它(https://code.google.com/p/jmockit/)完全基于 Java 5 SE 的 java.lang.instrument 包開發,內部使用 ASM 庫來修改Java的Bytecode。正是由于基于instrument,可以修改字節碼。所以這也是它強大的原因。

            Jmockit可以mock的種類包含了:1.class(abstract, final, static) ;2.interface ;3.enum ;4.annotation ;5.native 。

            Jmockit 有兩種mock的方式:

            1. Behavior-oriented(Expectations & Verifications)  ;

            2. State-oriented(MockUp<GenericType>)   。

            通俗點講,Behavior-oriented是基于行為的mock,對mock目標代碼的行為進行模仿,更像黑盒測試。State-oriented 是基于狀態的mock,是站在目標測試代碼內部的。可以對傳入的參數進行檢查、匹配,才返回某些結果,類似白盒。而State-oriented的 new MockUp基本上可以mock任何代碼或邏輯。非常強大。

            以下是jmockit的APIs和tools:

            可以看到jmockit常用的Expectation、NonStrictExpectations 期望錄制 及Annotation @Tested、@Mocked,@NonStrict、@Injectable 等簡潔的mock代碼風格。而且jmockit 還自帶了code coverage的工具供本地UT時候看邏輯覆蓋或代碼覆蓋率使用。

            五.Jmockit的實踐:

            第一步:添加jmockit的jar包依賴

            在refund的單元測試過程中,第一步:應用pom中引入jmockit的jar包,可以順帶引入jmockit自帶的code coverage的jar。

            第二步:一個完整的Jmockit的示例:


            這個是對refundmanager里面查詢可退款金額范圍 queryRefundFeeRange的單元測試。通過看被測代碼可以看到這個方法的實現里面調用了

            feeResultDO = confirmGoodsService.queryConfirmToSellerRefundFee(detailId);

            這個外部的hsf依賴 獲取了feeResultDO 。

            這個hsf調用是需要mock的。

            傳統的mock或ut ,對 confirmGoodsService 這個bean是需要初始化,通過spring的配置,初始化加載等 一大堆代碼。

            jmockit通過了注解的方式:

          @Injectable
          private ConfirmGoodsService confirmGoodsService ;

            一個Annotation就搞定了所有的配置,加載等問題。直接復用開發代碼里面的bean,節省了大量的代碼。

            另外  @Tested  RefundManagerImpl refundManagerImpl = new RefundManagerImpl();

            這里也用到了注解 @Tested   表示被測試的class 。

            另外還有常用的注解:@Mocked,@NonStrict等。

            而這段代碼就是mock的核心:錄制被mock的method的行為及期望返回:

          new Expectations(){
          {
          confirmGoodsService.queryConfirmToSellerRefundFee(anyLong);
          result = feeResultDOmock;
          times = 1;
          }
          } ;

            其中

            result  可以返回任意需要的測試類型;

            times  表示期望被調用的次數。

            是不是看起來非常簡潔明了。

            而上面該段代碼如果 換成基于狀態的mockup 代碼如下:

            采用MockUp的方式,可以mock任意的mock對象或方法,因為它直接改寫了原method的實現邏輯,直接返回需要的數據。

            這也是jmockit彪悍的地方之一。

            最后數據回收,防止各個testcase的mock相互影響的方式:

            Mockit.tearDownMocks();

            這一步也可以省略。

            還要重點介紹的就是mock期望里面的入參 any。


          這個any系列的萬能入參類型,也可以節省很多mock代碼,可以高效的準備任何入參類型。


            以上,一個最簡單的,也最實用的jmockit的示例。


            jmockit的更多,對interface及method的單元測試的示例,將在后續總結匯總。


            六、 Jmockit自帶的code coverage :


            工程的 pom文件中引入 jmockit-coverage 后,本地eclipse啟動單元測試后, 會自動統計單元測試的代碼覆蓋率。關于行覆蓋,方法覆蓋,類覆蓋,分支邏輯覆蓋等各種數據都可以看到。


            IDE啟動UT時候,加載 code coverage  組件,


            點擊進去,可以看到具體的覆蓋邏輯:


            其中綠色部分表示源代碼被run過。


            代碼覆蓋對指導單元測試的測試邏輯,覆蓋等提供了直觀的指示。


            以上,就是在單元測試中mock技術的應用:Jmockit的使用介紹及實際應用示例。它在單元測試中確實可以很少的代碼mock掉外部依賴,提高ut的效率,并且 自帶的code coverage可很方便的看到ut對被測代碼的覆蓋效果,指導測試設計。




          posted on 2013-07-25 10:40 順其自然EVO 閱讀(8130) 評論(0)  編輯  收藏 所屬分類: 測試學習專欄

          <2013年7月>
          30123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 宜春市| 富川| 乐清市| 衡南县| 梓潼县| 肃宁县| 确山县| 宜丰县| 泽普县| 黎城县| 渝北区| 柯坪县| 阿拉尔市| 水城县| 汨罗市| 淮安市| 长宁区| 丹阳市| 巴彦淖尔市| 墨竹工卡县| 于田县| 边坝县| 上林县| 宜兴市| 洪湖市| 乌海市| 宜川县| 江安县| 巴林左旗| 襄汾县| 镇远县| 内丘县| 哈尔滨市| 古交市| 南乐县| 新闻| 安吉县| 沅江市| 同心县| 壶关县| 奈曼旗|