<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一款優(yōu)秀的Java模擬框架:Mockito

          共 5175字,需瀏覽 11分鐘

           ·

          2021-01-14 14:23

          ?愿你越努力越幸運(yùn)?


          「歇一歇,繼續(xù)奔跑」

          日常的開發(fā)中,習(xí)慣性地寫完需求代碼后,嗖的一聲運(yùn)行一個(gè)main函數(shù)或?qū)憥讉€(gè)簡(jiǎn)單的JUnit的單元測(cè)試來跑功能點(diǎn),多寫幾個(gè)單元測(cè)試過沒有問題就可以上線了(其實(shí)這樣是不規(guī)范的),對(duì)于需要對(duì)接第三方或者驗(yàn)證不同條件的代碼分支邏輯時(shí),這種方法就會(huì)變得不可取,因?yàn)闃I(yè)務(wù)邏輯中需要依賴其他的接口,而這時(shí)候所依賴的接口還沒有準(zhǔn)備好,那我們應(yīng)該怎么辦呢?


          這時(shí)候該Mockito派上用場(chǎng)了,一方面使用Mockito可以屏蔽依賴接口并返回Mock數(shù)據(jù),使得雙方的開發(fā)得以同步進(jìn)行(確定接口的協(xié)議)編碼,另一方面使用Mockito驗(yàn)證業(yè)務(wù)邏輯,當(dāng)日后更改到某處代碼即可回歸測(cè)試用例看改動(dòng)是否覆蓋到所有的測(cè)試點(diǎn),因此使用Mockito不單單能保證代碼的質(zhì)量,更能提高代碼維護(hù)性、提前發(fā)現(xiàn)代碼的bug。



          Mock四要素


          • 什么是Mock

          在軟件開發(fā)的世界之外, "Mock"一詞是指模仿或者效仿。 因此可以將“Mock”理解為一個(gè)替身、替代者,在軟件開發(fā)中提及"Mock",通常理解為模擬對(duì)象或者Fake


          • 為什么需要Mock

          Mock是為了解決units、代碼分層開發(fā)之間由于耦合而難于被測(cè)試的問題,所以mock object是單元測(cè)試的一部分


          • Mock的好處是什么

          提前創(chuàng)建測(cè)試,提高代碼質(zhì)量、TDD(測(cè)試驅(qū)動(dòng)開發(fā))


          • 并行工作

          創(chuàng)建一個(gè)驗(yàn)證或者演示程序,為無法訪問的資源編寫測(cè)試



          什么是Mockito


          Mockito是一個(gè)非常優(yōu)秀的模擬框架,可以使用它簡(jiǎn)潔的API來編寫漂亮的測(cè)試代碼,它的測(cè)試代碼可讀性高同時(shí)會(huì)產(chǎn)生清晰的錯(cuò)誤日志。


          1、引入依賴:

          <dependency>    <groupId>org.mockitogroupId>    <artifactId>mockito-coreartifactId>    <version>3.3.3version>    <scope>testscope>dependency>

          注意:Mockito 3.X的版本使用了JDK8的API,但與2.X的版本并沒有太大的變化。


          2、在測(cè)試類中添加@RunWith注解,并制定Runner的類,即MockitoJUnitRunner

          @RunWith(MockitoJUnitRunner.class)public class MockitoDemoTest {    ????//注入依賴的資源對(duì)象    @Mock    private MockitoTestService mockitoTestService;    @Before    public void before(){        MockitoAnnotations.initMocks(this);    }}

          從代碼中可觀察到,使用@Mock標(biāo)識(shí)對(duì)象是被Mock的,同時(shí)在初始化前置執(zhí)行MockitoAnnotations.initMocks(this)告訴框架生Mock相關(guān)注解生效。


          3、驗(yàn)證對(duì)象的行為Verify

          @Testpublic void testVerify(){    //創(chuàng)建mock    List mockedList = mock(List.class);    mockedList.add("1");    mockedList.clear();    //驗(yàn)證list調(diào)用過add的操作行為    verify(mockedList).add("1");    //驗(yàn)證list調(diào)用過clear的操作行為    verify(mockedList).clear();    //使用內(nèi)建anyInt()參數(shù)匹配器,并存根    when(mockedList.get(anyInt())).thenReturn("element");    System.out.println(mockedList.get(2)); //此處輸出為element    verify(mockedList).get(anyInt());}


          4、存根—stubbing

          stubbing完全是模擬一個(gè)外部依賴,用來提供測(cè)試時(shí)所需要的測(cè)試數(shù)據(jù)

          @Testpublic void testStub(){    //可以mock具體的類,而不僅僅是接口    LinkedList mockedList = mock(LinkedList.class);    //存根(stubbing)    when(mockedList.get(0)).thenReturn("first");    when(mockedList.get(1)).thenThrow(new RuntimeException());    //下面會(huì)打印 "first"    System.out.println(mockedList.get(0));    //下面會(huì)拋出運(yùn)行時(shí)異常    System.out.println(mockedList.get(1));    //下面會(huì)打印"null" 因?yàn)間et(999)沒有存根(stub)    System.out.println(mockedList.get(999));    doThrow(new RuntimeException()).when(mockedList).clear();    //下面會(huì)拋出 RuntimeException:    mockedList.clear();}
          • 存根(stub)可以覆蓋:例如測(cè)試方法可以覆蓋通用存

          • 一旦做了存根方法將總是返回存根的值,無論這個(gè)方法被調(diào)用多少次


          5、存根的連續(xù)調(diào)用

          @Testpublic void testStub() {    when(mock.someMethod("some arg"))    .thenThrow(new RuntimeException())????.thenReturn("foo");    mock.someMethod("some arg"); //第一次調(diào)用:拋出運(yùn)行時(shí)異常    //第二次調(diào)用: 打印 "foo"    System.out.println(mock.someMethod("some arg"));    //任何連續(xù)調(diào)用: 還是打印 "foo" (最后的存根生效).    System.out.println(mock.someMethod("some arg"));    //可供選擇的連續(xù)存根的更短版本:    when(mock.someMethod("some arg")).thenReturn("one", "two", "three");    when(mock.someMethod(anyString())).thenAnswer(new Answer() {        Object answer(InvocationOnMock invocation) {            Object[] args = invocation.getArguments();            Object mock = invocation.getMock();            return "called with arguments: " + args;        }    });    // "called with arguments: foo    System.out.println(mock.someMethod("foo"));}


          6、參數(shù)匹配器

          @Testpublic void testArugument{    //使用內(nèi)建anyInt()參數(shù)匹配器    when(mockedList.get(anyInt())).thenReturn("element");    System.out.println(mockedList.get(999)); //打印 "element"    //同樣可以用參數(shù)匹配器做驗(yàn)證    verify(mockedList).get(anyInt());
          //注意:如果使用參數(shù)匹配器,所有的參數(shù)都必須通過匹配器提供。 verify(mock) .someMethod(anyInt(), anyString(), eq("third argument")); //上面是正確的 - eq(0也是參數(shù)匹配器),而下面的是錯(cuò)誤的 verify(mock) .someMethod(anyInt(), anyString(), "third argument");}


          7、驗(yàn)證精確調(diào)用次數(shù)/至少X次/從不

          @Testpublic void testVerify{    List mockedList = new ArrayList();    mockedList.add("once");    mockedList.add("twice");    mockedList.add("twice");    mockedList.add("three times");    mockedList.add("three times");    mockedList.add("three times");    //下面兩個(gè)驗(yàn)證是等同的 - 默認(rèn)使用times(1)    verify(mockedList).add("once");    verify(mockedList, times(1)).add("once");    verify(mockedList, times(2)).add("twice");    verify(mockedList, times(3)).add("three times");    //使用using never()來驗(yàn)證. never()相當(dāng)于 times(0)    verify(mockedList, never()).add("never happened");    //使用 atLeast()/atMost()來驗(yàn)證    verify(mockedList, atLeastOnce()).add("three times");    verify(mockedList, atLeast(2)).add("five times");    verify(mockedList, atMost(5)).add("three times");}


          8、驗(yàn)證調(diào)用順序

          @Testpublic void testOrder(){    // A. 單個(gè)Mock,方法必須以特定順序調(diào)用    List singleMock = mock(List.class);
          //使用單個(gè)Mock singleMock.add("was added first"); singleMock.add("was added second");
          //為singleMock創(chuàng)建 inOrder 檢驗(yàn)器 InOrder inOrder = inOrder(singleMock);
          //確保add方法第一次調(diào)用是用"was added first",然后是用"was added second" inOrder.verify(singleMock).add("was added first"); inOrder.verify(singleMock).add("was added second");}


          今天主要講Mockito的常用方式,下一篇將講解Spring Boot如何集成Mockito、JUnit、PowerMock做Mock單元測(cè)試。


          —————END—————


          推薦閱讀:



          最近面試BAT,整理一份面試資料Java面試BAT通關(guān)手冊(cè),覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點(diǎn)“在看”,關(guān)注公眾號(hào)并回復(fù)?666?領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          明天見(??ω??)??
          瀏覽 31
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  99国产在线观看免费 | 日韩无码三级 | 日一区二区三区四区视频 | 久久无码人妻 | av搬运一区二区三区在线观看 |