欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

spring中使用Mockito解決Bean依賴樹問題方法

 更新時間:2020年01月28日 11:15:29   作者:229  
在本篇文章里小編給各位整理了關(guān)于spring中使用Mockito解決Bean依賴樹問題方法,有需要的朋友們可以參考下。

前提

本文不是針對Mockito的入門教學(xué) ,主要敘述如何簡單的使用Mockito解決Bean依賴樹問題,對于Mockito的學(xué)習(xí)請找其他的文章或者查閱官方文檔

基本概念 Junit初始化及存在的問題

spring應(yīng)用在unit test時,test是獨(dú)立運(yùn)行的,所以需要自行 init ApplicationContext,啟動 Ioc容器。

Junit要求:Test類中涉及的所有Spring bean 注入成功才能完成applicationContext初始化,并啟動IOC容器,否則無法執(zhí)行unit test。

ApplicationContext初始化的兩種方式 手動注入(使用 @Bean或者 @Component 注入所需的類)編寫@Configuration 類(使用@ComponentScan 指定掃描beans) 兩種初始化方式存在的問題

方式一:

所需的beans中,一個bean少注入了就會導(dǎo)致無法初始化上下文需要注入的bean太多時,需要花費(fèi)大量的時間和精力,排查缺漏難度大

方式二:

顆粒度難以把控,隨著項目規(guī)模變大之后,可能導(dǎo)致bean導(dǎo)入過多,單元測試跑很久才能通過當(dāng)項目規(guī)模大了之后,bean之間的依賴往往是復(fù)雜的,掃描bean的方式可能出現(xiàn)一些不屬于自己模塊的未知問題或者某些中間件在unitTest環(huán)境無法正常啟動,導(dǎo)致無法初始化上下文 什么是依賴樹?

在開發(fā)應(yīng)用時,往往會出現(xiàn)如上圖的 樹型依賴 ,比如 serviceA 調(diào)用 serviceB,serviceB 又調(diào)用 serviceC 。

然而這只是一個簡單的例子。真正的開發(fā)中,往往一個 service 會依賴多個 service ,以及多個 dao ,以此來實現(xiàn)業(yè)務(wù)邏輯。

而根據(jù)Junit要求,我們必須將樹的路徑經(jīng)過的所有節(jié)點(diǎn)(bean)都注入才能完成spring上下文初始化。這時如果bean之間的依賴耦合過大時,就無法跳脫出兩種初始化方式帶來的問題。

什么是Mockito?

在測試過程中,對于某些不容易構(gòu)造(如 HttpServletRequest 必須在Servlet 容器中才能構(gòu)造出來)或者不容易獲取比較復(fù)雜的對象(如 JDBC 中的ResultSet 對象),用一個虛擬對象(Mock 對象)來創(chuàng)建以便測試的測試方法。

Mock 最大的功能是幫你把單元測試的耦合分解開,如果你的代碼對另一個類或者接口有依賴,它能夠幫你模擬這些依賴,并幫你驗證所調(diào)用的依賴的行為。

簡單來說:就是虛擬一個mock對象,這個對象在單元測試時會“貍貓換太子”,將原有bean進(jìn)行替換,“騙過”spring初始化,成功啟動ioc容器,以此規(guī)避常規(guī)初始化方式帶來的種種問題。

開發(fā)場景

結(jié)合本人在工作中遇見的問題,當(dāng)時我所寫的模塊進(jìn)行unitTest時,就出現(xiàn)了依賴樹過于龐大的問題。

首先,我采用了常規(guī)的手動注入(方式一),導(dǎo)致注入了很久都沒注入完,無法執(zhí)行測試。后來覺得這方法在這種情況不可行。然后,我采用了編寫@Configuration 類(方式二),同樣也存在一些問題。一些不屬于我負(fù)責(zé)模塊的bean也被注入,其中某些涉及TaskSchedule的bean無法被正確注入,導(dǎo)致無法執(zhí)行測試。此時一個個bean探索,解決問題顯然不現(xiàn)實。最后,我采用Junit+Mockito結(jié)合的方式進(jìn)行單元測試。按照依賴樹大小進(jìn)行區(qū)分。 依賴樹小的直接使用常規(guī)的手動注入(方式一),省事,同時保證大部分邏輯按照代碼正常運(yùn)行依賴樹大的使用Mockito,避免前文提到的兩種初始化方式導(dǎo)致的問題

使用 1 導(dǎo)入maven依賴

首先導(dǎo)入mockito maven依賴,版本請根據(jù)自己的spring版本選擇,否則會出現(xiàn)不兼容的情況。

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
      <exclusions>
        <exclusion>
          <groupId>org.junit.vintage</groupId>
          <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>

注意:

此處導(dǎo)入了spring-boot-starter-test是因為這個依賴已經(jīng)包含了mockito相關(guān)的jar包

spring-boot-starter-test可以使用 @MockBean 注解(mockito-core、mockito-all貌似不能)

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

@Mock @MockBean mock bean替換時機(jī) spring上下文初始化 完成之后 spring上下文初始化 執(zhí)行期間 能否“騙”過spring初始化否是 能否解決依賴樹否是 在沒注入所有所需的bean,無法完成spring上下文初始化時,@Mock無法正常工作 @MockBean在初始化時就進(jìn)行替換,spring上下文初始化時檢測的bean為替換后的mock bean,而mock bean本身是無依賴任何其他bean的,自然能夠“騙”過spring上下文初始化階段,成功啟動IOC容器 2 分析bean之間的依賴

使用一個簡單的Demo進(jìn)行開發(fā)場景的模擬,采用Junit+Mockito結(jié)合的方式進(jìn)行單元測試,根據(jù)依賴樹大小區(qū)分出是否需要mock

如圖,此處編寫了一個ControllerA,ControllerA中依賴了2個bean:ServiceA,DaoA

分析過程: 關(guān)于 DaoA :由于Dao往往不會依賴其他的bean,所以此處可以使用常規(guī)的手動注入(方式一)即可。方便快捷關(guān)于 ServiceA :由于serviceA依賴了serviceB(->DaoB)、serviceC(->DaoC),像這樣的嵌套依賴的bean就可以使用Mockito,來解決依賴樹問題 3 編寫Test類

daoA使用@Bean注解注入即可

@Bean
    public DaoA daoA(){
      return new DaoAImpl();
    }

1.serviceA首先使用@MockBean注解,將serviceA模擬為Mock Bean,它將在spring上下文初始化時就替換掉原有Bean

 @MockBean
  private ServiceA serviceA;

2.在test類執(zhí)行前(@Before),使用Mockito API設(shè)置調(diào)用某個方法的返回值(你預(yù)期得到的返回結(jié)果),在Test類中調(diào)用這個方法時就會返回所指定的值

@Before
  public void init(){
    MockitoAnnotations.initMocks(this);//只使用 @MockBean 時可省略這句
    when(controllerA.serviceA_method()).thenReturn("666");
  }

3.使用 @InjectMocks 通知依賴了serviceA的controllerA,在spring啟動時,對controllerA這個bean進(jìn)行相應(yīng)的后置處理

@Autowired
  @InjectMocks
  private ControllerA controller;

4.單元測試時,就不會使用原有Bean的方法,而是使用Mock Bean及其已經(jīng)指定了返回值的方法

@Test
  public void testDeepMock() {
    String s = controllerA.serviceA_method();
    System.out.println(s);
  }

5.unitTest結(jié)果


以上就是本次介紹的全部相關(guān)知識點(diǎn),感謝大家的學(xué)習(xí)和對腳本之家的支持。

相關(guān)文章

  • Java連接Redis全過程講解

    Java連接Redis全過程講解

    這篇文章主要介紹了Java連接Redis全過程講解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Spring深入刨析聲明式事務(wù)注解的源碼

    Spring深入刨析聲明式事務(wù)注解的源碼

    在spring注解中,使用聲明式事務(wù),需要用到兩個核心的注解:@Transactional注解和@EnableTransactionManagement注解。將@Transactional注解加在方法上,@EnableTransactionManagement注解加在配置類上
    2022-07-07
  • Java中的遞歸詳解(用遞歸實現(xiàn)99乘法表來講解)

    Java中的遞歸詳解(用遞歸實現(xiàn)99乘法表來講解)

    這篇文章主要介紹了Java中的遞歸詳解(用遞歸實現(xiàn)99乘法表來講解),本文給出了普通的99乘法實現(xiàn)方法和用遞歸實現(xiàn)的方法,并對比它們的不同,體現(xiàn)出遞歸的運(yùn)用及理解,需要的朋友可以參考下
    2015-03-03
  • Springboot?+redis+谷歌開源Kaptcha實現(xiàn)圖片驗證碼功能

    Springboot?+redis+谷歌開源Kaptcha實現(xiàn)圖片驗證碼功能

    這篇文章主要介紹了Springboot?+redis+?歌開源Kaptcha實現(xiàn)圖片驗證碼功能,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-01-01
  • Spring-webflux?響應(yīng)式編程的實例詳解

    Spring-webflux?響應(yīng)式編程的實例詳解

    Spring 提供了兩個并行堆棧,一種是基于帶有 Spring MVC 和 Spring Data 結(jié)構(gòu)的 Servlet API,另一個是完全反應(yīng)式堆棧,它利用了 Spring WebFlux 和 Spring Data 的反應(yīng)式存儲庫,這篇文章主要介紹了Spring-webflux?響應(yīng)式編程,需要的朋友可以參考下
    2022-09-09
  • 使用idea解決maven依賴沖突的問題

    使用idea解決maven依賴沖突的問題

    這篇文章主要介紹了使用idea解決maven依賴沖突,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • Spring整合Quartz實現(xiàn)動態(tài)定時器的示例代碼

    Spring整合Quartz實現(xiàn)動態(tài)定時器的示例代碼

    本篇文章主要介紹了Spring整合Quartz實現(xiàn)動態(tài)定時器的示例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-01-01
  • jar的MANIFEST.MF配置Class-Path, java -classpath設(shè)置無效的解決

    jar的MANIFEST.MF配置Class-Path, java -classpath設(shè)置無效的解

    這篇文章主要介紹了jar的MANIFEST.MF配置Class-Path, java -classpath設(shè)置無效的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Mybatis 創(chuàng)建方法、全局配置教程詳解

    Mybatis 創(chuàng)建方法、全局配置教程詳解

    MyBatis是一個半自動化的輕量級的持久化層框架。 MyBatis實際上是Ibatis3.0版本以后的持久化層框架,下面通過本文給大家分享Mybatis 創(chuàng)建方法、全局配置教程詳解,需要的朋友參考下吧
    2017-09-09
  • java中關(guān)于轉(zhuǎn)義字符的一個bug

    java中關(guān)于轉(zhuǎn)義字符的一個bug

    本文主要介紹了java中關(guān)于轉(zhuǎn)義字符的一個bug。具有很好的參考價值,下面跟著小編一起來看下吧
    2017-02-02

最新評論