最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

springboot集成測(cè)試容器重啟問題的處理

 更新時(shí)間:2021年11月03日 14:34:51   作者:micro_hz  
這篇文章主要介紹了springboot集成測(cè)試容器重啟問題的處理,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

背景

spring boot test的項(xiàng)目中常用的測(cè)試框架, 最近在寫集成測(cè)試的時(shí)候發(fā)現(xiàn)一個(gè)比較奇怪的問題,當(dāng)我在運(yùn)行多個(gè)測(cè)試用例的時(shí)候會(huì)偶爾重新啟動(dòng)整個(gè)容器上下文,由于后期業(yè)務(wù)逐漸復(fù)雜,大量的測(cè)試用例需要運(yùn)行,這個(gè)問題直接導(dǎo)致回歸測(cè)試的效率降低。

在這里插入圖片描述

舉個(gè)例子:

在這里插入圖片描述

幾個(gè)類:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class BaseApiTest {
    @Test
    public void init() {
    }
}
public class ApiTest1 extends BaseApiTest {
    @MockBean
    private Service service;
    @Test
    public void test1() {
        service.call();
    }
}
public class ApiTest2 extends BaseApiTest {
    @Autowired
    private Service service;
    @Test
    public void test2() {
        service.call();
    }
}
@SpringBootApplication
@Slf4j
public class TestApplication {
    public static void main(String[] args) {
        log.info("啟動(dòng)容器");
        new SpringApplication(TestApplication.class).run(args);
    }
}
@Component
public class Service {
    public void call() {
        System.out.println("service called");
    }
}

運(yùn)行test包下所有測(cè)試:

在這里插入圖片描述

發(fā)現(xiàn)容器重復(fù)啟動(dòng)了。

測(cè)試用例的運(yùn)行流程

可以開啟idea的線程堆棧跟蹤,觀察整個(gè)容器的啟動(dòng)路徑

在這里插入圖片描述

com.intellij.rt.junit是idea內(nèi)部的實(shí)現(xiàn),點(diǎn)擊idea的運(yùn)行單測(cè)會(huì)觸發(fā)JunitStarter的main函數(shù)去啟動(dòng),可以去GitHub找到源碼:

在這里插入圖片描述

做一些準(zhǔn)備工作找到指定的runner就開始調(diào)用junit的包去執(zhí)行編寫的單測(cè),junit為了靈活的擴(kuò)展不同的測(cè)試運(yùn)行環(huán)境,類似SPI機(jī)制動(dòng)態(tài)獲取Runner去運(yùn)行單測(cè)。例如我的例子里指定了SpringRunner就是需要依賴Spring容器的一個(gè)實(shí)現(xiàn),這樣就讓測(cè)試用例可以運(yùn)行在Spring環(huán)境中。

在這里插入圖片描述

junit的入口也支持在測(cè)例前后去插入一些操作,自己去實(shí)現(xiàn)RunnerListener即可。junit默認(rèn)實(shí)現(xiàn)了監(jiān)聽器去記錄測(cè)例的耗時(shí),失敗的數(shù)量等信息。

在這里插入圖片描述

我指定的Runner是SpringRunner,其與SpringJUnit4ClassRunner并沒什么區(qū)別,可以看其實(shí)現(xiàn)完全繼承了SpringJUnit4ClassRunner的實(shí)現(xiàn)。

所以我們直接看SpringJUnit4ClassRunner的runner實(shí)現(xiàn):

在這里插入圖片描述

它首先判斷了當(dāng)前的環(huán)境是否需要忽略單測(cè)。如果忽略會(huì)在通知里得到通知。關(guān)于環(huán)境的指定控制可以參考注解@IfProfileValue,判斷環(huán)境正確之后繼續(xù)調(diào)用junit包父類ParentRunner的方法執(zhí)行。

其定義了執(zhí)行的基本的模板:

在這里插入圖片描述

classBlock里面定義線程池執(zhí)行和測(cè)例執(zhí)行的一些before和after邏輯,里面的runChild是抽象方法,也是留給各個(gè)Runner實(shí)現(xiàn)的鉤子。getFilteredChildren能夠根據(jù)@Test注解拿到所有需要運(yùn)行的用例方法,然后每個(gè)方法去調(diào)用具體的Runner運(yùn)行。

在這里插入圖片描述

其流程圖如下

在這里插入圖片描述

在這里插入圖片描述

SpringJUnit4ClassRunner的運(yùn)行每個(gè)方法會(huì)給每個(gè)測(cè)例方法進(jìn)行一個(gè)封裝成Statement。關(guān)鍵就在methodBlock方法,它實(shí)現(xiàn)了Spring boot對(duì)方法運(yùn)行的封裝

在這里插入圖片描述

createTest會(huì)在測(cè)試的上下文里維護(hù)一個(gè)配置,然后會(huì)用通知機(jī)制一樣去依次調(diào)用需要準(zhǔn)備的東西,其中就包含spring容器的上下文。

在這里插入圖片描述

在這里插入圖片描述

其會(huì)執(zhí)行injectDependencies,處理依賴的bean準(zhǔn)備。TestContext是每個(gè)單測(cè)方法需要運(yùn)行的上下文,在Spring boot的測(cè)試環(huán)境下,其維護(hù)了Spring的上下文,每個(gè)方法的執(zhí)行都會(huì)去獲取Spring的上下文

在這里插入圖片描述

根據(jù)單測(cè)的相關(guān)信息文獲取上spring的上下文,為了避免每次都去加載容器,TestContext會(huì)維護(hù)一個(gè)spring容器的緩存,CacheAwareContextLoaderDelegate

在這里插入圖片描述

在這里插入圖片描述

CacheAwareContextLoaderDelegate其內(nèi)部的獲取又是通過單測(cè)配置信息去ContextCache獲取的,其內(nèi)部是一個(gè)同步SynchronizedMap去保存的。

在這里插入圖片描述

其內(nèi)部實(shí)現(xiàn)看測(cè)例的配置信息去獲取加載過的容器,如果沒獲取到就會(huì)觸發(fā)重新加載新容器的流程,所以關(guān)鍵就是看key在Map中的獲取邏輯,其底層是spring test自己實(shí)現(xiàn)一個(gè)的Map

在這里插入圖片描述

可以看到其是基于HashMap的一個(gè)哈希結(jié)構(gòu),根據(jù)Jdk的源碼,我們可以知道HashMap的key是根據(jù)hashCode與equals去比較key,那可以確定,要想復(fù)用同一個(gè)容器就得看Key值的hashCode和equals實(shí)現(xiàn)。接下來我們看MergedContextConfiguration源碼.

在這里插入圖片描述

在這里插入圖片描述

可以發(fā)現(xiàn)其比較的值是:

 	 * @param testClass the test class for which the configuration was merged
	 * @param locations the merged context resource locations
	 * @param classes the merged annotated classes
	 * @param contextInitializerClasses the merged context initializer classes
	 * @param activeProfiles the merged active bean definition profiles
	 * @param propertySourceLocations the merged {@code PropertySource} locations
	 * @param propertySourceProperties the merged {@code PropertySource} properties
	 * @param contextCustomizers the context customizers
	 * @param contextLoader the resolved {@code ContextLoader}
	 * @param cacheAwareContextLoaderDelegate a cache-aware context loader
	 * delegate with which to retrieve the parent context
	 * @param parent the parent configuration or {@code null} if there is no parent

這些參數(shù)確定了能否共享SpringApplication,那兩個(gè)測(cè)試類一個(gè)@Autowired,另一個(gè)使用@MockBean,肯定是改變這里面某個(gè)值,我們可以回溯這個(gè)MergedContextConfiguration是在什么時(shí)候被初始化的。這個(gè)還要追溯到idea的啟動(dòng)類,找到Runner的時(shí)候,SpringJUnit4ClassRunner的初始化的過程。

在每個(gè)測(cè)試類的運(yùn)行都會(huì)喚起SpringJUnit4ClassRunner初始化,調(diào)用構(gòu)造函數(shù)的時(shí)候會(huì)去加載測(cè)試類的上下文

Texrt

去創(chuàng)建這個(gè)TextContextManager

在這里插入圖片描述

這里首先會(huì)根據(jù)被測(cè)試類的繼承關(guān)系和注解的遞歸去找到固定包下面被注解@BootstrapWith修飾的類,因?yàn)槭荢pring boot test這里會(huì)根據(jù)@SpringBootTest 注解找到SpringBootTestContextBootstrapper類,找到這個(gè)引導(dǎo)類之后就會(huì)去初始化MergedContextConfiguration了。

在這里插入圖片描述

引導(dǎo)類通過SPI機(jī)制加載到所有的Customizer,并根據(jù)需要DefinitionsParser,進(jìn)行轉(zhuǎn)換,保存在MergedContextConfiguration的一個(gè)字段,mock的一個(gè)屬性會(huì)在轉(zhuǎn)換的時(shí)候記錄到,而非mock的contextCustomizers則不會(huì)記錄。

注意這里提到的

在這里插入圖片描述

在這里插入圖片描述

兩個(gè)類一個(gè)用mock的字段,一個(gè)用非mock的字段,兩個(gè)MockitoContextCustomizer的definitions就不一樣,因此無法共享上下文,因此需要重新啟動(dòng)一個(gè)Spring容器,并存放到CacheAwareContextLoaderDelegate,以便后面共享。

結(jié)論

分析源碼的設(shè)計(jì),發(fā)現(xiàn)應(yīng)用了很多SPI與可擴(kuò)展的設(shè)計(jì),idea與junit的解耦,junit的抽象與模板定義與各個(gè)測(cè)試框架的擴(kuò)展。

針對(duì)容器重啟的角度,對(duì)于一個(gè)類來說,一定是共享一個(gè)spring上下文,但是不同的類可能由于注入的bean的方式不同導(dǎo)致無法共享spring上下文,所以導(dǎo)致重啟會(huì)浪費(fèi)掉一些時(shí)間,因此建議確定好mock的邊界,對(duì)盡量多的測(cè)例共享一個(gè)容器視角可以提高單測(cè)效率,基于此可以設(shè)計(jì)多繼承關(guān)系的單測(cè)結(jié)構(gòu),并把注入的bean向上共享,避免各個(gè)測(cè)試子類自己去注入出現(xiàn)不一致的情況。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Maven?Settings.xml的基本語法詳解

    Maven?Settings.xml的基本語法詳解

    這篇文章主要為大家介紹了Maven?Settings.xml的基本語法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • 在Eclipse IDE使用Gradle構(gòu)建應(yīng)用程序(圖文)

    在Eclipse IDE使用Gradle構(gòu)建應(yīng)用程序(圖文)

    這篇文章主要介紹了在Eclipse IDE使用Gradle構(gòu)建應(yīng)用程序(圖文),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-12-12
  • Mybatis 動(dòng)態(tài)表名+Map參數(shù)傳遞+批量操作詳解

    Mybatis 動(dòng)態(tài)表名+Map參數(shù)傳遞+批量操作詳解

    這篇文章主要介紹了Mybatis 動(dòng)態(tài)表名+Map參數(shù)傳遞+批量操作詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Spring發(fā)送郵件如何內(nèi)嵌圖片增加附件

    Spring發(fā)送郵件如何內(nèi)嵌圖片增加附件

    這篇文章主要介紹了Spring發(fā)送郵件如何內(nèi)嵌圖片增加附件,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • JavaWeb學(xué)習(xí)筆記分享(必看篇)

    JavaWeb學(xué)習(xí)筆記分享(必看篇)

    下面小編就為大家?guī)硪黄狫avaWeb學(xué)習(xí)筆記分享(必看篇)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-06-06
  • java開發(fā)Dubbo注解Adaptive實(shí)現(xiàn)原理

    java開發(fā)Dubbo注解Adaptive實(shí)現(xiàn)原理

    這篇文章主要為大家介紹了java開發(fā)Dubbo注解Adaptive實(shí)現(xiàn)原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • springboot aop切到service層,不生效問題

    springboot aop切到service層,不生效問題

    這篇文章主要介紹了springboot aop切到service層,不生效問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • java數(shù)據(jù)結(jié)構(gòu)算法稀疏數(shù)組示例詳解

    java數(shù)據(jù)結(jié)構(gòu)算法稀疏數(shù)組示例詳解

    這篇文章主要為大家介紹了java數(shù)據(jù)結(jié)構(gòu)算法稀疏數(shù)組示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • javaweb實(shí)現(xiàn)文件上傳示例代碼

    javaweb實(shí)現(xiàn)文件上傳示例代碼

    這篇文章主要為大家詳細(xì)介紹了javaweb實(shí)現(xiàn)文件上傳的示例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • 基于Java實(shí)現(xiàn)模板填充Word

    基于Java實(shí)現(xiàn)模板填充Word

    這篇文章主要為大家詳細(xì)介紹了如何用?Java?實(shí)現(xiàn)按產(chǎn)品經(jīng)理提供的?Word?模板填充數(shù)據(jù),并以?word?或?pdf?形式導(dǎo)出,有需要的小伙伴可以參考一下
    2025-01-01

最新評(píng)論

罗城| 金华市| 松原市| 伊金霍洛旗| 普兰县| 沙洋县| 泽州县| 井研县| 务川| 河北区| 漯河市| 广河县| 田阳县| 虹口区| 夹江县| 沿河| 景德镇市| 朝阳县| 深圳市| 雷山县| 浦东新区| 宾阳县| 银川市| 武义县| 北海市| 沐川县| 东方市| 云浮市| 上林县| 南澳县| 屏南县| 彭泽县| 金湖县| 肥西县| 江山市| 武夷山市| 上饶市| 洪湖市| 惠安县| 莱芜市| 潢川县|