亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java Springboot 后端使用Mockito庫(kù)進(jìn)行單元測(cè)試流程分析

 更新時(shí)間:2024年10月15日 11:27:52   作者:Bling_  
使用Mock進(jìn)行單元測(cè)試可以避免啟動(dòng)整個(gè)Spring框架,節(jié)省時(shí)間并降低外部依賴影響,Mock允許模擬外部方法和類,專注于測(cè)試方法的功能邏輯,本文給大家介紹Java Springboot 后端使用Mockito庫(kù)進(jìn)行單元測(cè)試流程分析,感興趣的朋友跟隨小編一起看看吧

1 為什么要使用mock進(jìn)行單元測(cè)試

如果使用SpringbootTest進(jìn)行單元測(cè)試,那么將啟動(dòng)spring服務(wù),生成容器和bean并加載所有外部資源或依賴,當(dāng)工程量很大時(shí)啟動(dòng)非常費(fèi)時(shí),顯然為了一個(gè)小小的單元測(cè)試啟動(dòng)整個(gè)項(xiàng)目有一些大動(dòng)干戈。

此外,有時(shí)部分外部依賴無(wú)法獲?。ㄈ鐢?shù)據(jù)庫(kù)連接、緩存或接口獲取有問(wèn)題),而單元測(cè)試旨在測(cè)試某個(gè)類具體的方法,測(cè)試的是該方法的功能邏輯,不應(yīng)關(guān)注其依賴的對(duì)象,以防測(cè)試時(shí)各級(jí)方法互相調(diào)用太深(調(diào)用的方法應(yīng)該在它自己的單元測(cè)試中進(jìn)行測(cè)試),相當(dāng)于只關(guān)注測(cè)試方法的寬度而不在意它的深度。

因此,對(duì)于要測(cè)試的方法中使用到的外部類或方法,可以考慮使用模擬對(duì)象來(lái)模擬它們的調(diào)用并自定義好返回的值,這樣能夠在不執(zhí)行真實(shí)調(diào)用方法的同時(shí)讓單元測(cè)試正常進(jìn)行,這就是mock的原理。使用mock可以很好的將要測(cè)試的方法和它的依賴分隔開(kāi),降低了模塊間的耦合,非常適合外部資源較難構(gòu)造或方法調(diào)用太深的場(chǎng)景。

2 使用mock的注意點(diǎn)

  • 通過(guò)mock進(jìn)行單元測(cè)試時(shí)并未啟動(dòng)spring,那么不會(huì)加載容器并生成bean,就無(wú)法通過(guò)自動(dòng)注入的方式獲取依賴,需要使用mock注解
  • 如果測(cè)試的相關(guān)功能與spring有關(guān)(比如AOP),那么還是需要使用SpringbootTest
  • 啟用mock時(shí)可以看成啟動(dòng)了普通的java項(xiàng)目,在普通項(xiàng)目中能運(yùn)行的代碼在mock中也能運(yùn)行
  • 單元測(cè)試時(shí)并非所有調(diào)用的外部方法或使用到的外部類都需要mock,如實(shí)體類可以直接new,工具類方法可以直接運(yùn)行(不存在外部依賴的工具類,比如用來(lái)進(jìn)行數(shù)據(jù)格式處理的工具類,通常調(diào)用其靜態(tài)方法),不需要使用mock

3 mock使用流程

3.1 測(cè)試前配置

使用mock首先需要在pom文件中導(dǎo)入相關(guān)依賴,然后可以使用@Mock或Mockito庫(kù)的mock方法來(lái)生成模擬對(duì)象,如果使用@Mock則需要先添加以下注解代碼:

  • 在測(cè)試類前添加@RunWith(MockitoJUnitRunner.class)@ExtendWith(MockitoExtension.class)
  • 在測(cè)試類內(nèi)添加如下方法:
//測(cè)試前準(zhǔn)備,可以在這里進(jìn)行一些基礎(chǔ)配置
@BeforeEach
    void setUp(){
        MockitoAnnotations.openMocks(this); //開(kāi)啟mock,搭配@Mock使用
}

3.2 注入待測(cè)試類并模擬其中使用的變量

若需要測(cè)試的類為UserService,那么在它的測(cè)試類UserServiceTest中需要使用注解@InjectMocks注入UserService的實(shí)例,該注解的作用是自動(dòng)創(chuàng)建并注入一個(gè)類的實(shí)例,同時(shí)將標(biāo)記為@Mock的依賴注入到該實(shí)例中,注意@InjectMocks只能注入class。

@InjectMocks
UserService userService;

3.2.1 模擬成員變量

待測(cè)試類的成員變量需要使用@Mock注解注入,無(wú)法通過(guò)Mockito.mock()方法生成模擬對(duì)象,mock()方法生成的成員模擬對(duì)象在執(zhí)行時(shí)會(huì)報(bào)空指針錯(cuò)誤,并未真正生成模擬對(duì)象。
UserService中有成員變量UserMapper,那么使用如下代碼注入:

@Mock
UserMapper

簡(jiǎn)單來(lái)說(shuō)就是將UserService里面的所有成員變量直接復(fù)制到Test里,然后將@Autowired改成@Mock即可。

3.2.2 模擬靜態(tài)對(duì)象

當(dāng)代碼中需要調(diào)用某個(gè)類的靜態(tài)方法時(shí),需要使用mockStatic()方法生成一個(gè)模擬靜態(tài)對(duì)象,如被測(cè)方法中若存在如下代碼:

DictUtil.getIns("A_END"); //DictUtil類中存在一些外部依賴,因此需要模擬

那么首先需要生成DictUtil的模擬靜態(tài)對(duì)象:

mockStatic(DictUtil.class);  //上下兩種寫法都可以
MockedStatic<DictUtil> dictUtilMockedStatic = mockStatic(DictUtil.class);

3.2.3 模擬普通變量

對(duì)于代碼中生成的一些中間變量,而在后期又需要使用這些變量進(jìn)行方法調(diào)用時(shí),需要先使用mock將中間變量模擬出,如被測(cè)方法中若存在代碼:

UserCache.getInstance().getName("12345");

那么需要先模擬出UserCache的一個(gè)實(shí)例(打樁時(shí)不能對(duì)連續(xù)調(diào)用的方法同時(shí)打樁,需先生成中間變量),此時(shí)可以使用@Mock或者mock方法:

// 1. 當(dāng)成測(cè)試類成員變量注入
@Mock
UserCache userCache;
// 2. 在測(cè)試方法中直接模擬
UserCache userCache = Mockito.mock(UserCache.class);

3.3 打樁模擬方法調(diào)用行為

3.3.1 非靜態(tài)方法打樁

打樁即對(duì)調(diào)用的方法模擬傳參并設(shè)置返回值,參數(shù)個(gè)數(shù)和返回值需要與原方法對(duì)應(yīng)。打樁之后不會(huì)真正去調(diào)用,會(huì)忽略真實(shí)方法的執(zhí)行結(jié)果,一般使用Mockito.when().thenReturn()進(jìn)行打樁。
若被測(cè)類方法中存在代碼:

User user = UserMapper.selectById("0000");

那么測(cè)試方法中的打樁可以是:

//實(shí)體類不需要mock,可以直接生成,然后使用setter方法賦值
User user = new User();
// 1. 固定了打樁參數(shù)為“0000”,源代碼調(diào)用中參數(shù)為非“0000”時(shí)打樁失敗
Mockito.when(UserMapper.selectById("0000")).thenReturn(user)
// 2. 為了代碼的健壯性,通常使用Mockito.anyxxx()方法來(lái)接收參數(shù),根據(jù)xxx的不同來(lái)指定不同的類型,只要是該類型的任意參數(shù)都可以打樁
Mockito.when(UserMapper.selectById(Mockito.anyString())).thenReturn(user)

3.3.2 靜態(tài)方法打樁

以原代碼UserCache.getInstance().getName("12345");為例,靜態(tài)方法打樁有兩種寫法:
1) 普通寫法

UserCache userCache = Mockito.mock(UserCache.class);
mockStatic(UserCache.class);  
Mockito.when(UserCache.getInstance()).thenReturn(userCache);
Mockito.when(userCache.getName(Mockito.anyString())).thenReturn("TestName");

2) lambda寫法-無(wú)參靜態(tài)方法調(diào)用

UserCache userCache = Mockito.mock(UserCache.class);
MockedStatic<UserCache> userCacheMockedStatic = mockStatic(UserCache.class);
//1. 當(dāng)靜態(tài)方法無(wú)參時(shí),可以使用::進(jìn)行方法調(diào)用
userCacheMockedStatic.when(UserCache::getInstance).thenReturn(userCache);
//2. 也可以使用lambda寫法,使用.進(jìn)行調(diào)用
userCacheMockedStatic.when(() -> UserCache.getInstance()).thenReturn(userCache);
//3. 不能使用如下寫法:
//userCacheMockedStatic.when(UserCache.getInstance()).thenReturn(userCache);
Mockito.when(userCache.getName(Mockito.anyString())).thenReturn("TestName");

3) lambda寫法-有參靜態(tài)方法調(diào)用
假如上述getInstance方法有一個(gè)int參數(shù),那么可以通過(guò)1)中的普通寫法進(jìn)行打樁,或者使用2)-2的方式進(jìn)行打樁,然后使用Mockito.anyString()傳參,但是不能使用2)-1或2)-3的寫法。

3.3.3 Maven test靜態(tài)模擬報(bào)錯(cuò)問(wèn)題

當(dāng)單獨(dú)運(yùn)行一個(gè)Test時(shí)沒(méi)有問(wèn)題,但是當(dāng)集體執(zhí)行Test時(shí)會(huì)出現(xiàn)如下報(bào)錯(cuò):

‘static mocking is already registered in the current thread To create a new mock, the existing static mock registration must be deregistered’

這是因?yàn)橛袃蓚€(gè)以上的測(cè)試方法都使用了同一個(gè)靜態(tài)mock對(duì)象,如兩個(gè)Test中都有MockedStatic<UserCache> userCacheMockedStatic = mockStatic(UserCache.class),而靜態(tài)mock對(duì)象不允許公用,因此需要在每個(gè)靜態(tài)mock對(duì)象執(zhí)行后對(duì)其進(jìn)行關(guān)閉,下一個(gè)方法才能繼續(xù)使用它,故需要在每個(gè)Test末尾中寫:userCacheMockedStatic.close()。
由于MockedStatic<T>的父接口繼承了AutoCloseable接口,因此可以使用 try-resources語(yǔ)句實(shí)現(xiàn)資源的自動(dòng)關(guān)閉:

try(
	// mockStatic(UserCache.class);  //java8不支持這種寫法
	MockedStatic<UserCache> userCacheMockedStatic = mockStatic(UserCache.class);
	// ……其他靜態(tài)模擬對(duì)象聲明
){
    //其他測(cè)試代碼
}

也可以選擇用try-catch-finally在finally語(yǔ)句里手動(dòng)關(guān)閉:

try(
	MockedStatic<UserCache> userCacheMockedStatic = mockStatic(UserCache.class);
	// ……其他測(cè)試代碼
)finally{
    userCacheMockedStatic.close();
}

3.4 斷言判斷測(cè)試結(jié)果

要檢測(cè)測(cè)試的結(jié)果,需要使用斷言Assertions進(jìn)行判斷,根據(jù)實(shí)際測(cè)試要求來(lái):

User user = UserService.getById("123");
User expectUsr = new User("123");
Assertions.assertEquals(expectUsr ,user)://判斷測(cè)試結(jié)果user與期望的對(duì)象是否一致
Assertions.assertNotNull(user)://判斷測(cè)試結(jié)果user是否非空

到此這篇關(guān)于Java Springboot 后端使用Mockito庫(kù)進(jìn)行單元測(cè)試流程的文章就介紹到這了,更多相關(guān)Springboot Mockito單元測(cè)試內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳細(xì)講解Java的泛型

    詳細(xì)講解Java的泛型

    這篇文章主要介紹了Java的泛型,是Java入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-09-09
  • 詳解如何更改SpringBoot TomCat運(yùn)行方式

    詳解如何更改SpringBoot TomCat運(yùn)行方式

    這篇文章主要介紹了詳解如何更改SpringBoot TomCat運(yùn)行方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 線程阻塞喚醒工具 LockSupport使用詳解

    線程阻塞喚醒工具 LockSupport使用詳解

    這篇文章主要為大家介紹了線程阻塞喚醒工具LockSupport使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • Mybatis ResultType如何處理返回類型

    Mybatis ResultType如何處理返回類型

    這篇文章主要介紹了Mybatis ResultType如何處理返回類型方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Spring Cloud Gateway 默認(rèn)的filter功能和執(zhí)行順序介紹

    Spring Cloud Gateway 默認(rèn)的filter功能和執(zhí)行順序介紹

    這篇文章主要介紹了Spring Cloud Gateway 默認(rèn)的filter功能和執(zhí)行順序,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Java?@Accessors注解圖文詳解

    Java?@Accessors注解圖文詳解

    @Accessors用于改變@Data生成的getter和setter方法的生成結(jié)果,下面這篇文章主要給大家介紹了關(guān)于Java?@Accessors注解的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • intellij idea的快速配置使用詳細(xì)教程

    intellij idea的快速配置使用詳細(xì)教程

    這篇文章主要介紹了intellij idea的快速配置使用詳細(xì)教程,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • SpringBoot2.3新特性優(yōu)雅停機(jī)詳解

    SpringBoot2.3新特性優(yōu)雅停機(jī)詳解

    這篇文章主要介紹了SpringBoot2.3新特性優(yōu)雅停機(jī)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • 淺談Java中的this作為返回值時(shí)返回的是什么

    淺談Java中的this作為返回值時(shí)返回的是什么

    Java中的this作為返回值時(shí)返回的是什么?下面小編就為大家介紹一下Java中的this作為返回值時(shí)返回。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-11-11
  • 解讀thymeleaf模板引擎中th:if的使用

    解讀thymeleaf模板引擎中th:if的使用

    這篇文章主要介紹了解讀thymeleaf模板引擎中th:if的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10

最新評(píng)論