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

Mockito如何mock靜態(tài)方法問(wèn)題

 更新時(shí)間:2025年02月25日 10:53:16   作者:cab5  
本文介紹了如何在Mockito 3.4.0版本及以上版本中mock靜態(tài)方法,包括如何在pom文件中添加相關(guān)jar包、如何使用Mockito.mockStatic(Class mockClass)方法以及注意事項(xiàng)等

Mockito如何mock靜態(tài)方法

在實(shí)際工作當(dāng)中,我們經(jīng)常會(huì)遇到需要對(duì)靜態(tài)方法進(jìn)行 mock 的情況。在 mockito 2.x 的時(shí)代,我們需要借助 powmock 才能實(shí)現(xiàn)。

當(dāng) mockito 進(jìn)化到了 3.4.0 版本以后,也開(kāi)始對(duì)靜態(tài)方法 mock 進(jìn)行了支持(主要是通過(guò) mockito-inline 包)。

簡(jiǎn)單的介紹就到這里,下面讓我們進(jìn)入主題吧。

1.首先確保pom文件中

mockito 相關(guān) jar 包的版本(這里我用的版本是 3.7.7),如下:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>3.7.7</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>3.7.7</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>3.7.7</version>
    <scope>test</scope>
</dependency>
<dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <version>4.13</version>
     <scope>test</scope>
 </dependency>

2.使用方式

Mockito.mockStatic(Class mockClass),如下:

// 這里 DateUtil 內(nèi)提供了靜態(tài)方法
MockedStatic<DateUtil> dateUtil = mockStatic(DateUtil.class);

示例:

import static org.mockito.Mockito.mockStatic;

@RunWith(MockitoJUnitRunner.class)
public class AlphaServiceTest {

    @Test
    public void testHttp() {
        ...
        
        MockedStatic<HTTPClient> httpClient = mockStatic(HTTPClient.class);
        httpClient.when(() -> HTTPClient.sendPost("xxx/zzz/ccc", "hello")).thenReturn("success");
        
        ...
        
        // 關(guān)閉
        httpClient.close();
    }
    

這樣基本上就 OK 了。

唯一需要注意下的就是 httpClient.close(),這個(gè)問(wèn)題會(huì)在「3.其他」中 “錯(cuò)誤提示 static mocking is already registered in the current thread To create a new mock, the existing static mock registration must be deregistered” 進(jìn)行詳細(xì)說(shuō)明)

3.其他

如果項(xiàng)目中未引入 mockito-inline,會(huì)出現(xiàn)如下錯(cuò)誤信息:

org.mockito.exceptions.base.MockitoException: 
The used MockMaker SubclassByteBuddyMockMaker does not support the creation of static mocks

Mockito's inline mock maker supports static mocks based on the Instrumentation API.
You can simply enable this mock mode, by placing the 'mockito-inline' artifact where you are currently using 'mockito-core'.
Note that Mockito's inline mock maker is not supported on Android.

    at com.annoroad.order.service.PreOrderServiceTestCase.testSaveClinicalFreeSuccess1(PreOrderServiceTestCase.java:86)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)

錯(cuò)誤提示

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

當(dāng)多個(gè)單元測(cè)試都使用了同一個(gè) static mock 對(duì)象,且使用完成后都沒(méi)有進(jìn)行 close。此時(shí),若這幾個(gè)單元測(cè)試用一起執(zhí)行,第一個(gè)單元測(cè)試占用了 static mock 對(duì)象,第二個(gè)單元測(cè)試就沒(méi)有辦法再占用了。

如果出現(xiàn)了這種情況,解決辦法也很簡(jiǎn)單,就是關(guān)閉 static mock 對(duì)象,如下:

import static org.mockito.Mockito.mockStatic;

@RunWith(MockitoJUnitRunner.class)
public class AlphaServiceTest {

    @Test
    public void testHttp1() {
        ...
        
        MockedStatic<HTTPClient> httpClient = mockStatic(HTTPClient.class);
        httpClient.when(() -> HTTPClient.sendPost("xxx/zzz/ccc", "hello")).thenReturn("success");
        
        ...

		httpClient.close();
    }
    
    @Test
    public void testHttp2() {
        ...
        
        MockedStatic<HTTPClient> httpClient = mockStatic(HTTPClient.class);
        httpClient.when(() -> HTTPClient.sendPost("xxx/zzz/ccc", "hello")).thenReturn("success");
        
        ...

		httpClient.close();
    }
    
    @Test
    public void testHttp3() {
        ...
        
        MockedStatic<HTTPClient> httpClient = mockStatic(HTTPClient.class);
        httpClient.when(() -> HTTPClient.sendPost("xxx/zzz/ccc", "hello")).thenReturn("success");
        
        ...
		
		httpClient.close();
    }

如果你的很多單元測(cè)試中都用到了 mockStatic(HTTPClient.class),且覺(jué)得在每個(gè)單元測(cè)試當(dāng)中都寫(xiě)一遍 mockStatic()…close() 很低效,可以采用下邊的方式:

import static org.mockito.Mockito.mockStatic;

@RunWith(MockitoJUnitRunner.class)
public class AlphaServiceTest {
	private MockedStatic<HttpClietn> httpClient;

	// 每個(gè)單元測(cè)試啟動(dòng)前,先執(zhí)行該方法(高版本中 @Before 被替換成 @BeforeEach)
    @Before
    public void setUp() {
        this.httpClient = mockStatic(HTTPClient.class);
    }
    
	// 每個(gè)單元測(cè)試執(zhí)行完成后,執(zhí)行該方法(高版本中 @After 被替換成 @AfterEach)
    @After
    public void teardown() {
        this.httpClient.close();
    }

    @Test
    public void testHttp1() {
        ...
        
        httpClient.when(() -> HTTPClient.sendPost("xxx/zzz/ccc", "hello")).thenReturn("success");
        
        ...
    }
    
    @Test
    public void testHttp2() {
        ...
        
        httpClient.when(() -> HTTPClient.sendPost("xxx/zzz/ccc", "hello")).thenReturn("success");
        
        ...
    }
    
    @Test
    public void testHttp3() {
        ...
        
        httpClient.when(() -> HTTPClient.sendPost("xxx/zzz/ccc", "hello")).thenReturn("success");
        
        ...
    }

這樣就清爽多了 ~:)

總結(jié)

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

相關(guān)文章

  • SpringCloud_Sleuth分布式鏈路請(qǐng)求跟蹤的示例代碼

    SpringCloud_Sleuth分布式鏈路請(qǐng)求跟蹤的示例代碼

    Spring Cloud Sleuth是一款針對(duì)Spring Cloud的分布式跟蹤工具,本文通過(guò)實(shí)例代碼介紹了SpringCloud_Sleuth分布式鏈路請(qǐng)求跟蹤,感興趣的朋友跟隨小編一起看看吧
    2023-02-02
  • jdk中String類設(shè)計(jì)成final的原由

    jdk中String類設(shè)計(jì)成final的原由

    為什么jdk中把 String 類設(shè)計(jì)成final,主要是為了“ 效率 ”和“安全性”的緣故,若 String 允許被繼承, 由于它的高度被使用率, 可能會(huì)降低程序的性能,所以String被定義成final,需要了解的朋友可以參考下
    2013-01-01
  • 基于Springboot實(shí)現(xiàn)送水公司信息管理系統(tǒng)

    基于Springboot實(shí)現(xiàn)送水公司信息管理系統(tǒng)

    這篇文章主要介紹了基于Springboot實(shí)現(xiàn)送水公司信息管理,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-01-01
  • Spring 中優(yōu)雅的獲取泛型信息的方法

    Spring 中優(yōu)雅的獲取泛型信息的方法

    這篇文章主要介紹了Spring 中優(yōu)雅的獲取泛型信息的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • SpringBoot自定義Starter與自動(dòng)配置實(shí)現(xiàn)方法詳解

    SpringBoot自定義Starter與自動(dòng)配置實(shí)現(xiàn)方法詳解

    在Spring Boot官網(wǎng)為了簡(jiǎn)化我們的開(kāi)發(fā),已經(jīng)提供了非常多場(chǎng)景的Starter來(lái)為我們使用,即便如此,也無(wú)法全面的滿足我們實(shí)際工作中的開(kāi)發(fā)場(chǎng)景,這時(shí)我們就需要自定義實(shí)現(xiàn)定制化的Starter
    2023-02-02
  • 淺談Zookeeper開(kāi)源客戶端框架Curator

    淺談Zookeeper開(kāi)源客戶端框架Curator

    這篇文章主要介紹了淺談Zookeeper開(kāi)源客戶端框架Curator的相關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-10-10
  • SpringBoot參數(shù)校驗(yàn)的方法總結(jié)

    SpringBoot參數(shù)校驗(yàn)的方法總結(jié)

    今天帶大家學(xué)習(xí)SpringBoot參數(shù)校驗(yàn)的方法,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好地幫助,需要的朋友可以參考下
    2021-05-05
  • java后臺(tái)批量下載文件并壓縮成zip下載的方法

    java后臺(tái)批量下載文件并壓縮成zip下載的方法

    這篇文章主要為大家詳細(xì)介紹了java后臺(tái)批量下載文件并壓縮成zip下載的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • spring mvc 和ajax異步交互完整實(shí)例代碼

    spring mvc 和ajax異步交互完整實(shí)例代碼

    本篇文章主要介紹了spring mvc 和ajax異步交互完整實(shí)例代碼,簡(jiǎn)單的AJAX+SpringMVC的異步交互小例子,有興趣的可以了解一下。
    2017-02-02
  • 關(guān)于微服務(wù)使用Dubbo設(shè)置的端口和server.port的區(qū)別

    關(guān)于微服務(wù)使用Dubbo設(shè)置的端口和server.port的區(qū)別

    這篇文章主要介紹了關(guān)于微服務(wù)使用Dubbo設(shè)置的端口和server.port的區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12

最新評(píng)論