乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Powermock2.0.0 詳細(xì) 總結(jié)

       印度阿三17 2019-04-13

      目錄

      1 單元測試

      自己認(rèn)為,單元測試最重要的作用有如下兩點(diǎn)

      ①開發(fā)人員實(shí)現(xiàn)某個(gè)功能或者修補(bǔ)了某個(gè)bug,如果有相應(yīng)的單元測試支持的話,開發(fā)人員可以馬上通過運(yùn)行單元測試來驗(yàn)證之前完成的代碼是否正確,而不需要反復(fù)通過發(fā)布war包、啟動jboss、通過瀏覽器輸入數(shù)據(jù)等繁瑣的步驟來驗(yàn)證所完成的功能

      ②保證你最后的代碼修改不會破壞之前代碼的功能。項(xiàng)目越做越大,代碼越來越多,特別涉及到一些公用接口之類的代碼或是底層的基礎(chǔ)庫,誰也不敢保證這次修改的代碼不會破壞之前的功能,所以與此相關(guān)的需求會被擱置或推遲,由于不敢改進(jìn)代碼,代碼也變得越來越難以維護(hù),質(zhì)量也越來越差。而單元測試就是解決這種問題的很好方法(不敢說最好的)。由于代碼的歷史功能都有相應(yīng)的單元測試保證,修改了某些代碼以后,通過運(yùn)行相關(guān)的單元測試就可以驗(yàn)證出新調(diào)整的功能是否有影響到之前的功能。當(dāng)然要實(shí)現(xiàn)到這種程度需要很大的付出,不但要能夠達(dá)到比較高的測試覆蓋率,而且單元測試代碼的編寫質(zhì)量也要有保證

      2 Junit測試框架

      2.1 Junit是什么

      JUnit是一個(gè)Java語言的單元測試框架。它由Kent Beck和Erich Gamma建立,逐漸成為源于Kent Beck的sUnit的xUnit家族中最為成功的一個(gè)JUnit有它自己的JUnit擴(kuò)展生態(tài)圈。多數(shù)Java的開發(fā)環(huán)境都已經(jīng)集成了JUnit作為單元測試的工具。

      注意:Junit 測試也是程序員測試,即所謂的白盒測試,它需要程序員知道被測試的代碼如何完成功能,以及完成什么樣的功能

      2.2 Junit 能做什么?

      我們知道 Junit 是一個(gè)單元測試框架,那么使用 Junit 能讓我們快速的完成單元測試。

      通常我們寫完代碼想要測試這段代碼的正確性,那么必須新建一個(gè)類,然后創(chuàng)建一個(gè) main() 方法,然后編寫測試代碼。如果需要測試的代碼很多呢?那么要么就會建很多main() 方法來測試,要么將其全部寫在一個(gè) main() 方法里面。這也會大大的增加測試的復(fù)雜度,降低程序員的測試積極性。而 Junit 能很好的解決這個(gè)問題,簡化單元測試,寫一點(diǎn)測一點(diǎn),在編寫以后的代碼中如果發(fā)現(xiàn)問題可以較快的追蹤到問題的原因,減小回歸錯(cuò)誤的糾錯(cuò)難度。

      3 Junit測試的局限性

      1、在某些非常復(fù)雜的業(yè)務(wù)邏輯,會準(zhǔn)備大量的數(shù)據(jù)。

      2、有的時(shí)候會依賴數(shù)據(jù)庫,中間件、文件系統(tǒng)等外部環(huán)境,這個(gè)時(shí)候我們不能控制這些外部依賴的對象。

      試想一下,如果我們依賴真實(shí)的數(shù)據(jù)庫環(huán)境,那么每次的單元測試結(jié)果可能都是不一樣的

      為了解決上述兩個(gè)問題,我們需要使用Mock技術(shù)

      4 Mock技術(shù)

      截取一段stackflow中的解釋:

      Mocking isprimarily used in unit testing. An object under test may have dependencies onother (complex) objects. To isolate the behaviour of the object you want totest you replace the other objects by mocks that simulate the behavior of thereal objects. This is useful if the real objects are impractical to incorporateinto the unit test. 
      MOCK主要被用于在單測中,某個(gè)對象在測試過程中有可能依賴于其他的復(fù)雜對象,通過mocks去模擬真實(shí)的其他對象(模塊)去代替你想要去測試的其他的對象(模塊),如果其他對象(模塊)是很難從單元測試中剝離開來的話,這是非常有用的

      Mock有以下幾個(gè)好處:

      1、Mock可以用來解除測試對象對外部服務(wù)的依賴(比如數(shù)據(jù)庫,第三方接口等),使得測試用例可以獨(dú)立運(yùn)行。不管是傳統(tǒng)的單體應(yīng)用,還是現(xiàn)在流行的微服務(wù),這點(diǎn)都特別重要,因?yàn)槿魏瓮獠恳蕾嚨拇嬖诙紩O大的限制測試用例的可遷移性和穩(wěn)定性??蛇w移性是指,如果要在一個(gè)新的測試環(huán)境中運(yùn)行相同的測試用例,那么除了要保證測試對象自身能夠正常運(yùn)行,還要保證所有依賴的外部服務(wù)也能夠被正常調(diào)用。穩(wěn)定性是指,如果外部服務(wù)不可用,那么測試用例也可能會失敗。通過Mock去除外部依賴之后,不管是測試用例的可遷移性還是穩(wěn)定性,都能夠上一個(gè)臺階。

      2、Mock的第二個(gè)好處是替換外部服務(wù)調(diào)用,提升測試用例的運(yùn)行速度。任何外部服務(wù)調(diào)用至少是跨進(jìn)程級別的消耗,甚至是跨系統(tǒng)、跨網(wǎng)絡(luò)的消耗,而Mock可以把消耗降低到進(jìn)程內(nèi)。比如原來一次秒級的網(wǎng)絡(luò)請求,通過Mock可以降至毫秒級,整整3個(gè)數(shù)量級的差別

      3、Mock的第三個(gè)好處是提升測試效率。這里說的測試效率有兩層含義。第一層含義是單位時(shí)間運(yùn)行的測試用例數(shù),這是運(yùn)行速度提升帶來的直接好處。而第二層含義是一個(gè)測試人員單位時(shí)間創(chuàng)建的測試用例數(shù)。如何理解這第二層含義呢?以單體應(yīng)用為例,隨著業(yè)務(wù)復(fù)雜度的上升,為了運(yùn)行一個(gè)測試用例可能需要準(zhǔn)備很多測試數(shù)據(jù),與此同時(shí)還要盡量保證多個(gè)測試用例之間的測試數(shù)據(jù)互不干擾。為了做到這一點(diǎn),測試人員往往需要花費(fèi)大量的時(shí)間來維護(hù)一套可運(yùn)行的測試數(shù)據(jù)。有了Mock之后,由于去除了測試用例之間共享的數(shù)據(jù)庫依賴,測試人員就可以針對每一個(gè)或者每一組測試用例設(shè)計(jì)一套獨(dú)立的測試數(shù)據(jù),從而很容易的做到不同測試用例之間的數(shù)據(jù)隔離性。而對于微服務(wù),由于一個(gè)微服務(wù)可能級聯(lián)依賴很多其他的微服務(wù),運(yùn)行一個(gè)測試用例甚至需要跨系統(tǒng)準(zhǔn)備一套測試數(shù)據(jù),如果沒有Mock,基本上可以說是不可能的。因此,不管是單體應(yīng)用還是微服務(wù),有了Mock之后,QE就可以省去大量的準(zhǔn)備測試數(shù)據(jù)的時(shí)間,專注于測試用例本身,自然也就提升了單人的測試效率。

      5 相關(guān)的Mock工具

      5.1 Mockito、EasyMock

      EasyMock 以及 Mockito 都因?yàn)榭梢詷O大地簡化單元測試的書寫過程而被許多人應(yīng)用在自己的工作中,但是這兩種 Mock 工具都不可以實(shí)現(xiàn)對靜態(tài)函數(shù)、構(gòu)造函數(shù)、私有函數(shù)、Final 函數(shù)以及系統(tǒng)函數(shù)的模擬,但是這些方法往往是我們在大型系統(tǒng)中需要的功能。

      5.2 powermock

      PowerMock是一個(gè)擴(kuò)展了其它如EasyMock等mock框架的、功能更加強(qiáng)大的框架。PowerMock使用一個(gè)自定義類加載器和字節(jié)碼操作來模擬靜態(tài)方法,構(gòu)造函數(shù),final類和方法,私有方法,去除靜態(tài)初始化器等等。通過使用自定義的類加載器,簡化采用的IDE或持續(xù)集成服務(wù)器不需要做任何改變。熟悉PowerMock支持的mock框架的開發(fā)人員會發(fā)現(xiàn)PowerMock很容易使用,因?yàn)閷τ陟o態(tài)方法和構(gòu)造器來說,整個(gè)的期望API是一樣的。PowerMock旨在用少量的方法和注解擴(kuò)展現(xiàn)有的API來實(shí)現(xiàn)額外的功能。目前PowerMock支持EasyMock和Mockito。

      5.3 mock底層原理

      ①M(fèi)ockito底層使用了動態(tài)代理,用到了CGLIB。因此需要被mock的對象,Mockito都會生成一個(gè)子類繼承該類,這也就是為什么final類、private方法、static方法不可以被Mock的原因

      ②powermock的底層原理

      我們首先看powermock的依賴

      可以看出來,它有兩個(gè)重要的依賴:javassist和objenesis。
      javassist是一個(gè)修改java字節(jié)碼的工具包,objenesis是一個(gè)繞過構(gòu)造方法來實(shí)例化一個(gè)對象的工具包。由此看來,PowerMock的本質(zhì)是通過修改字節(jié)碼來實(shí)現(xiàn)對靜態(tài)和final等方法的mock的

      下面是PowerMock的簡單實(shí)現(xiàn)原理:

      • 當(dāng)某個(gè)測試方法被注解@PrepareForTest標(biāo)注以后,在運(yùn)行測試用例時(shí),會創(chuàng)建一個(gè)新的org.powermock.core.classloader.MockClassLoader實(shí)例,然后加載該測試用例使用到的類(系統(tǒng)類除外)。

      • PowerMock會根據(jù)你的mock要求,去修改寫在注解@PrepareForTest里的class文件(當(dāng)前測試類會自動加入注解中),以滿足特殊的mock需求。例如:去除final方法的final標(biāo)識,在靜態(tài)方法的最前面加入自己的虛擬實(shí)現(xiàn)等。

      • 如果需要mock的是系統(tǒng)類的final方法和靜態(tài)方法,PowerMock不會直接修改系統(tǒng)類的class文件,而是修改調(diào)用系統(tǒng)類的class文件,以滿足mock需求。

      6 powermock的使用

      這里吐血推薦一本電子書
      網(wǎng)盤鏈接: https://pan.baidu.com/s/1ZndwumRgSTqmtn__RNVosA 密碼:e8w4

      7 springboot和powermock整合

      一定要注意powermock的版本號,我在這里就踩了很多坑,血淋淋的教訓(xùn)啊,由于公司與springboot繼承用的是最新的powermock,截止2019年4月12日,powermock-module-junit4的Maven地址倉庫最新版本是2.0.0 ,也正是powermock使用的太新了,導(dǎo)致后面遇到的問題,百度google根本無法解決(因?yàn)樗麄兌歼€停留在1.x版本中),最后也是通過github官方文檔才最終解決的

      <dependency>
          <groupId>org.powermock</groupId>
          <artifactId>powermock-module-junit4</artifactId>
          <version>2.0.0</version>
          <scope>test</scope>
          </dependency>
          <dependency>
          <groupId>org.powermock</groupId>
          <artifactId>powermock-api-mockito</artifactId>
          <version>2.0.0</version>
      <scope>test</scope>
      </dependency>

      7.1 重要注解

      @SpringBootTest  // 表明這是一個(gè)springboot測試類,會自動加載springboot主啟動程序
      @RunWith(PowerMockRunner.class) //使用powermock自己的Runner
      @PowerMockRunnerDelegate(SpringRunner.class) //將powermock整合到spring容器中
      @PowerMockIgnore({"javax.*.*", "com.sun.*", "org.xml.*", "org.apache.*"})
      @PrepareForTest({HSSFWorkbook.class,HSSFCellStyle.class})
      public class Demo {
      
          @Test
          public void test() throws Exception {
              EmployeeService service = PowerMockito.mock(EmployeeService.class);
              PowerMockito.when(service.hello()).thenReturn(999);
              int result = service.hello();
              Assert.assertEquals(999, result);
          }
      
      }

      下面主要對上面幾個(gè)注解做相關(guān)解釋:

      @SpringBootTest:表明這是一個(gè)springboot測試類,會自動加載springboot主啟動程序

      @RunWith(PowerMockRunner.class): 使用powermock自己的Runner

      @PowerMockRunnerDelegate(SpringRunner.class): 將powermock整合到spring容器中

      @PowerMockIgnore({"javax.*.*", "com.sun.", "org.xml.", "org.apache.*"}) : 這個(gè)注解很重要,這也是powermock2.0.0與1.x版本重大不一樣的地方,因?yàn)閜owermock自帶一個(gè)類加載器,使用該注解來禁止powermock類加載器加載一些類,避免和JVM類加載器沖突

      @PrepareForTest({HSSFWorkbook.class,HSSFCellStyle.class}): 這個(gè)注解是告訴PowerMock為我提前準(zhǔn)備一個(gè)xxx的class,根據(jù)我測試預(yù)期的行為去準(zhǔn)備

      至此,springboot和powermock的整合就完成了!

      7.2 PrepareForTest不能隨便加

      首先來看一段代碼:不使用@PrepareForTest

      @SpringBootTest
      @RunWith(PowerMockRunner.class)
      @PowerMockRunnerDelegate(SpringRunner.class)
      @PowerMockIgnore({"javax.*.*", "com.sun.*", "org.xml.*", "org.apache.*"})
      // @PrepareForTest({HSSFWorkbook.class,HSSFCellStyle.class}) 不使用該注解
      public class Demo {
          @Test 
          public void test() throws Exception{
              HSSFWorkbook wb = new HSSFWorkbook();
              wb.createSheet();
          }
      }

      程序運(yùn)行成功!

      使用@PrepareForTest

      @SpringBootTest
      @RunWith(PowerMockRunner.class)
      @PowerMockRunnerDelegate(SpringRunner.class)
      @PowerMockIgnore({"javax.*.*", "com.sun.*", "org.xml.*", "org.apache.*"})
      @PrepareForTest({HSSFWorkbook.class}) 
      public class Demo {
          @Test 
          public void test() throws Exception{
              HSSFWorkbook wb = new HSSFWorkbook();
              wb.createSheet();
          }
      }

      我們在test()測試中完全沒有用到powermock,但是為什么會失敗呢?

      原因:@PrepareForTest中的HSSFWorkbook.class,會告訴powermock提前準(zhǔn)備這個(gè)類文件,那么當(dāng)程序執(zhí)行的時(shí)候,需要的該類的時(shí)候,就會使用到powermock準(zhǔn)備的類

      到目前為止,讀者可能會認(rèn)為 HSSFWorkbook wb = new HSSFWorkbook();將會創(chuàng)建powermock準(zhǔn)備的HSSFWorkbook對象,那么我debug程序,一探究竟

      可以看到,這里new HSSFWorkbook()對象完全是一個(gè)正常的對象,而非powermock的對象,并且在該類中使用的也是這個(gè)真對象

      直到運(yùn)行到MockGateway這個(gè)類 才出現(xiàn)問題,在powermock中會有大量的代理類,攔截器,這些類中會使用到pokwermock的HSSFWorkbook的對象,而非真正的HSSFWorkbook對象,因此會出現(xiàn)問題

      7.3 不是所有的類都可以Powermock

      一個(gè)私有類是完全可以powermock的,那么是不是所有的類都可以powermock嗎?

      答案是:否定的()

      @SpringBootTest
      @RunWith(PowerMockRunner.class)
      @PowerMockRunnerDelegate(SpringRunner.class)
      @PowerMockIgnore({"javax.*.*", "com.sun.*", "org.xml.*", "org.apache.*"})
      @PrepareForTest({HSSFWorkbook.class})
      public class Demo {
          
          @Test
          public void test3() throws Exception{
              PowerMockito.mock(HSSFCellStyle.class);
          }
          
      }

      定位至HSSFCellStyle 133行

      我們發(fā)現(xiàn)這是一個(gè)編譯期常量,跟ThreadLocal,是沒辦法跟powermock對象一起創(chuàng)建的

      切記:powermock對象是無法改變編譯期常量的

      7.4 @InjectMock @Mock區(qū)別

          @InjectMocks
          private SomeHandler someHandler;
       
          @Mock 或者 @Spy
          private OneDependency oneDependency; // 此mock將被注入到someHandler

      這里的@InjectMocks和@Autowired功能完完全全一樣,唯一不同的是,@InjectMocks可以使oneDependency這個(gè)Mock對象自動注入到someHandler這個(gè)對象中。注意:①@InjectMocks所表示的對象及someHandler是一個(gè)普通的對象 ②Mock所表示的對象及oneDependency是一個(gè)Mock對象

      7.5 @Mock和@MockBean的區(qū)別

      @MockBean 會被裝配到相關(guān)的類中 代替@Autowired

      @Mock 不會被裝配到相關(guān)的類中 無法代替@Autowired

      7.6 Mock方法中的嵌套方法

      Mockito.when(alarmRulesDao.changeAlarmLevel(Mockito.anyInt(),Mockito.anyInt()))
                      .thenReturn(-1);
      
      Integer changeNumber = alarmRulesDao.changeAlarmLevel(changeAlarmlevelRequest.getId(), changeAlarmlevelRequest.getAlarmLevel());

      即使Mock了changeAlarmLevel方法,其中的

      changeAlarmlevelRequest.getId()
      changeAlarmlevelRequest.getAlarmLevel()

      還是會正常執(zhí)行的

      7.7 mock對象中的參數(shù)不要再做運(yùn)算

      this.getHSSFWorkbook(downloadVO.getSheetName(), downloadList));

      mock的時(shí)候不能

      Mockito.anyString(),Mockito.anyList()

      而要

      Mockito.any(),Mockito.anyList() 因?yàn)閙ock對象中的參數(shù)執(zhí)行了相關(guān)運(yùn)算

      參考資料:

      https://zhidao.baidu.com/question/390585793246337165.html

      https://www.cnblogs.com/ysocean/p/6889906.html

      http://www./post/355904

      https://www.cnblogs.com/hunterCecil/p/5721468.html

      https://qicen./blog/1928257

      請尊重作者勞動成果,轉(zhuǎn)載請注明出處。以上內(nèi)容若有侵權(quán),請聯(lián)系作者,立即刪除。來源:http://www./content-4-162901.html

        本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多