使用JUnit 5和Mockito能有效隔離依賴進行單元測試,1. 通過@Mock創(chuàng)建模擬對象,@InjectMocks注入被測實例,@ExtendWith啟用Mockito擴展;2. 使用when().thenReturn()定義模擬行為,verify()驗證方法調(diào)用次數(shù)與參數(shù);3. 可模擬異常場景並驗證錯誤處理;4. 推薦構(gòu)造函數(shù)注入、避免過度模擬、保持測試原子性;5. 使用assertAll()合併斷言,@Nested組織測試場景,從而提升測試可維護性和可靠性。
單元測試和模擬在Java中是保證代碼質(zhì)量的重要手段,而JUnit 5和Mockito是目前最流行的測試框架組合。它們配合使用,可以高效地對業(yè)務邏輯進行隔離測試,尤其適用於依賴外部服務、數(shù)據(jù)庫或複雜對象的場景。

為什麼使用JUnit 5 Mockito?
JUnit 5 是Java 中主流的單元測試框架,提供了更靈活的註解模型、擴展機制和斷言功能。 Mockito 則是一個強大的模擬(mocking)框架,允許你創(chuàng)建和配置“假”對象來替代真實依賴,從而專注於測試目標類的行為。
兩者結(jié)合,能讓你:

- 隔離被測代碼與外部依賴
- 驗證方法調(diào)用次數(shù)和參數(shù)
- 模擬異常和邊界情況
- 提高測試可維護性和執(zhí)行速度
1. 基本環(huán)境搭建
首先確保項目中引入了JUnit 5 和Mockito 的依賴。如果你使用Maven,添加以下內(nèi)容到pom.xml
:
<dependencies> <!-- JUnit 5 --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>5.10.0</version> <scope>test</scope> </dependency> <!-- Mockito --> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>5.7.0</version> <scope>test</scope> </dependency> <!-- Mockito JUnit Jupiter 支持(可選,用於@Mock 註解自動初始化) --> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-junit-jupiter</artifactId> <version>5.7.0</version> <scope>test</scope> </dependency> </dependencies>
同時,確保使用支持JUnit 5 的構(gòu)建配置(如Surefire 插件版本>= 2.22.0)。

2. 使用Mockito 模擬依賴對象
假設我們有一個訂單服務OrderService
,它依賴於一個支付網(wǎng)關(guān)PaymentGateway
接口:
public interface PaymentGateway { boolean charge(double amount); } public class OrderService { private final PaymentGateway paymentGateway; public OrderService(PaymentGateway paymentGateway) { this.paymentGateway = paymentGateway; } public boolean processOrder(double amount) { if (amount <= 0) return false; return paymentGateway.charge(amount); } }
我們想測試OrderService.processOrder()
,但不想真正調(diào)用支付系統(tǒng)。這時就可以用Mockito 創(chuàng)建一個模擬的PaymentGateway
。
編寫測試類
import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; class OrderServiceTest { @Mock private PaymentGateway paymentGateway; @InjectMocks private OrderService orderService; // 必須配合MockitoExtension 才能自動初始化@Mock 和@InjectMocks @org.junit.jupiter.api.extension.ExtendWith(MockitoExtension.class) static class Nested {} @Test void shouldReturnFalse_WhenAmountIsInvalid() { // 調(diào)用被測方法boolean result = orderService.processOrder(-100); // 斷言結(jié)果assertFalse(result); // 驗證沒有調(diào)用支付網(wǎng)關(guān)verify(paymentGateway, never()).charge(anyDouble()); } @Test void shouldReturnTrue_WhenPaymentSucceeds() { // 模擬依賴行為when(paymentGateway.charge(100.0)).thenReturn(true); // 執(zhí)行boolean result = orderService.processOrder(100.0); // 斷言assertTrue(result); verify(paymentGateway).charge(100.0); } @Test void shouldReturnFalse_WhenPaymentFails() { when(paymentGateway.charge(100.0)).thenReturn(false); boolean result = orderService.processOrder(100.0); assertFalse(result); verify(paymentGateway).charge(100.0); } }
關(guān)鍵點說明:
-
@Mock
:創(chuàng)建一個模擬對象(mock) -
@InjectMocks
:創(chuàng)建目標類實例,並自動將@Mock
標記的字段注入進去(通過構(gòu)造函數(shù)或字段注入) -
@ExtendWith(MockitoExtension.class)
:啟用Mockito 的JUnit 擴展,自動初始化註解 when(...).thenReturn(...)
:定義模擬方法的返回值verify(...)
:驗證某個方法是否被調(diào)用,以及調(diào)用次數(shù)、參數(shù)等
3. 驗證行為與交互(Behavior Verification)
除了斷言返回值,還可以驗證方法是否被正確調(diào)用。例如:
@Test void shouldAttemptChargeExactlyOnce() { when(paymentGateway.charge(50.0)).thenReturn(true); orderService.processOrder(50.0); // 驗證charge 方法被調(diào)用一次,且參數(shù)為50.0 verify(paymentGateway, times(1)).charge(eq(50.0)); }
其他常用驗證方式:
-
never()
:從未被調(diào)用 atLeastOnce()
:至少一次timeout(100)
:在指定時間內(nèi)被調(diào)用(用於異步)-
inOrder(...)
:驗證調(diào)用順序
// 示例:驗證調(diào)用順序InOrder inOrder = inOrder(paymentGateway); inOrder.verify(paymentGateway).charge(30.0); inOrder.verify(paymentGateway).charge(20.0);
4. 處理異常和邊界情況
你可以讓模擬對象拋出異常,測試錯誤處理邏輯:
@Test void shouldHandlePaymentFailureDueToException() { when(paymentGateway.charge(100.0)).thenThrow(new RuntimeException("Network error")); assertThrows(RuntimeException.class, () -> { orderService.processOrder(100.0); }); verify(paymentGateway).charge(100.0); }
也可以使用doThrow()
配合doReturn()
處理void
方法或特殊場景。
5. 小技巧和最佳實踐
- 避免過度模擬:只模擬真正需要隔離的依賴,不要模擬整個鏈路
- 優(yōu)先使用構(gòu)造函數(shù)注入:便於測試時傳入mock 對象
- 保持測試原子性:一個測試只驗證一個行為
- 使用
assertAll()
批量斷言
@Test void multipleAssertions() { when(paymentGateway.charge(100.0)).thenReturn(true); boolean result = orderService.processOrder(100.0); assertAll( () -> assertTrue(result), () -> verify(paymentGateway).charge(100.0) ); }
- 使用
@Nested
測試類組織不同場景:
@Nested class WhenAmountIsPositive { @Test void shouldChargePaymentGateway() { ... } }
基本上就這些。 JUnit 5 Mockito 的組合讓Java 單元測試變得直觀又強大。關(guān)鍵是理解“測試行為”而非“測試實現(xiàn)”,並通過mock 控制依賴,確保測試快速、穩(wěn)定、可重複。
以上是使用Junit 5和Mockito在Java進行單位測試和嘲笑的詳細內(nèi)容。更多資訊請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

熱AI工具

Undress AI Tool
免費脫衣圖片

Undresser.AI Undress
人工智慧驅(qū)動的應用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6
視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

懶加載在訪問關(guān)聯(lián)時才查詢,易導致N 1問題,適合不確定是否需要關(guān)聯(lián)數(shù)據(jù)的場景;2.急加載使用with()提前加載關(guān)聯(lián)數(shù)據(jù),避免N 1查詢,適合批量處理場景;3.應優(yōu)先使用急加載優(yōu)化性能,可通過LaravelDebugbar等工具檢測N 1問題,並謹慎使用模型的$with屬性以避免不必要的性能開銷。

usearestapitobridgephpandmlmodelsbyrunningthemodelinpythonviaflaskorfastapiandcallingitfromphpusingcurlorguzzle.2.runpythonscriptsdirectsdirectlyectlyectlyfromphpsingexec()orshell_exec()orshell_exec()orshell_exec()

Laravel支持使用原生SQL查詢,但應優(yōu)先使用參數(shù)綁定以確保安全;1.使用DB::select()執(zhí)行帶參數(shù)綁定的SELECT查詢,防止SQL注入;2.使用DB::update()執(zhí)行UPDATE操作並返回影響行數(shù);3.使用DB::insert()插入數(shù)據(jù);4.使用DB::delete()刪除數(shù)據(jù);5.使用DB::statement()執(zhí)行如CREATE、ALTER等無結(jié)果集的SQL語句;6.推薦在QueryBuilder中使用whereRaw、selectRaw等方法結(jié)合原生表達式以提升安

響應式編程在Java中通過ProjectReactor和SpringWebFlux實現(xiàn)高並發(fā)、低延遲的非阻塞服務。 1.ProjectReactor提供Mono和Flux兩個核心類型,支持聲明式處理異步數(shù)據(jù)流,並通過操作符鏈進行轉(zhuǎn)換、過濾等操作;2.SpringWebFlux基於Reactor構(gòu)建,支持註解式和函數(shù)式兩種編程模型,運行在Netty等非阻塞服務器上,可高效處理大量並發(fā)連接;3.使用WebFlux Reactor能提升I/O密集型場景下的並發(fā)能力與資源利用率,天然支持SSE、WebSo

JWT是一種用於安全傳輸信息的開放標準,在Java中可通過JJWT庫實現(xiàn)認證與授權(quán),1.添加JJWT的API、Impl和Jackson依賴;2.創(chuàng)建JwtUtil工具類生成、解析和驗證Token;3.編寫JwtFilter攔截請求併校驗Authorization頭中的BearerToken;4.在SpringBoot中註冊Filter保護指定路徑;5.提供登錄接口在驗證用戶後返回JWT;6.受保護接口通過解析Token獲取用戶身份和角色進行訪問控制,最終實現(xiàn)無狀態(tài)、可擴展的安全機制,適合分佈式系

Go泛型從1.18開始支持,用於編寫類型安全的通用代碼。 1.泛型函數(shù)PrintSlice[Tany](s[]T)可打印任意類型切片,如[]int或[]string。 2.通過類型約束Number限制T為int、float等數(shù)字類型,實現(xiàn)Sum[TNumber](slice[]T)T安全求和。 3.泛型結(jié)構(gòu)體typeBox[Tany]struct{ValueT}可封裝任意類型值,配合NewBox[Tany](vT)*Box[T]構(gòu)造函數(shù)使用。 4.為Box[T]添加Set(vT)和Get()T方法,無需

table-layout:fixed會強製表格列寬由第一行單元格寬度決定,避免內(nèi)容影響佈局。 1.設置table-layout:fixed並指定表格寬度;2.為第一行th/td設置具體列寬比例;3.配合white-space:nowrap、overflow:hidden和text-overflow:ellipsis控製文本溢出;4.適用於後臺管理、數(shù)據(jù)報表等需穩(wěn)定佈局和高性能渲染的場景,能有效防止佈局抖動並提升渲染效率。

使用JUnit5和Mockito能有效隔離依賴進行單元測試,1.通過@Mock創(chuàng)建模擬對象,@InjectMocks注入被測實例,@ExtendWith啟用Mockito擴展;2.使用when().thenReturn()定義模擬行為,verify()驗證方法調(diào)用次數(shù)與參數(shù);3.可模擬異常場景並驗證錯誤處理;4.推薦構(gòu)造函數(shù)注入、避免過度模擬、保持測試原子性;5.使用assertAll()合併斷言,@Nested組織測試場景,從而提升測試可維護性和可靠性。
