Mock與Stub


一、核心概念與差異對比

特性MockStub
核心目的驗證對象間的交互行為提供預定義的固定響應
驗證重點方法調用次數、參數、順序不關注調用過程,只關注結果
行為模擬可編程的智能模擬靜態的簡單響應
適用場景驗證協作關系隔離依賴、提供固定數據
復雜性較高(需要設置預期行為)較低(簡單硬編碼響應)

架構決策點:選擇Mock還是Stub取決于測試目標 - 驗證交互行為用Mock,替換依賴項用Stub


二、架構設計中的分層應用

測試金字塔中的定位
UI Tests
Integration Tests
Unit Tests
Mock
Stub
  • 單元測試層:Mock主導(驗證類間協作)
  • 集成測試層:Stub主導(模擬外部依賴)
  • 端到端測試:真實依賴(不使用模擬)
Spring測試架構
// 典型Spring測試分層
@SpringBootTest // 集成測試
class IntegrationTest {@MockBean DependencyService service; // MockBean替代真實依賴@Test void testIntegration() {// 使用Stub提供預設數據given(service.getData()).willReturn(new Data("stub value"));}
}@ExtendWith(MockitoExtension.class) // 單元測試
class UnitTest {@Mock Dependency dependency;@InjectMocks ServiceUnderTest service;@Test void testBehavior() {// 設置Mock行為并驗證交互when(dependency.process(any())).thenReturn(true);service.execute();verify(dependency, times(1)).process(any());}
}

三、Spring生態中的實現詳解

1. Stub實現方案

場景:為支付網關提供測試響應

// 定義支付網關接口
public interface PaymentGateway {PaymentResult charge(Order order);
}// 創建Stub實現
public class StubPaymentGateway implements PaymentGateway {private final PaymentResult fixedResult;public StubPaymentGateway(PaymentResult result) {this.fixedResult = result;}@Overridepublic PaymentResult charge(Order order) {// 靜態響應,不包含業務邏輯return fixedResult;}
}// 測試中使用
@Test
void testOrderProcessingWithStub() {// 創建帶成功響應的StubPaymentGateway stubGateway = new StubPaymentGateway(new PaymentResult("SUCCESS", "TX-123"));OrderService service = new OrderService(stubGateway);Order order = new Order(100.0);service.process(order);assertThat(order.getStatus()).isEqualTo(OrderStatus.PAID);
}
2. Mock實現方案(Mockito框架)

場景:驗證庫存服務調用

@ExtendWith(MockitoExtension.class)
class InventoryServiceTest {@Mock InventoryRepository mockRepo; // 創建Mock對象@InjectMocks InventoryService inventoryService; // 注入被測試對象@Testvoid shouldUpdateInventoryWhenOrderPaid() {// 準備測試數據Order order = new Order("order-1");order.addItem("prod-001", 2);// 設置Mock行為when(mockRepo.findByProductId("prod-001")).thenReturn(new Inventory("prod-001", 10));// 執行測試inventoryService.updateInventory(order);// 驗證交互行為verify(mockRepo, times(1)).findByProductId("prod-001");verify(mockRepo, times(1)).save(argThat(inv -> inv.getQuantity() == 8)); // 驗證保存參數// 驗證未發生的方法調用verify(mockRepo, never()).delete(any());}
}

四、高級模式與應用場景

1. 部分Mock(Spy對象)

場景:測試復雜服務中的特定方法

@Spy // 部分Mock:真實對象+可Mock特定方法
private EmailService emailService;@Test
void testOrderNotification() {// 模擬發送郵件方法doNothing().when(emailService).sendConfirmation(any());orderService.processOrder(order);verify(emailService).sendConfirmation(order);
}
2. Spring Cloud Contract(契約測試)

架構方案:跨服務邊界的Stub管理

生成Stub
測試時下載
Provider
Stub Repository
Consumer

提供方(定義契約):

// payment-contract.groovy
Contract.make {request {method POST()url '/payments'body([orderId: anyUuid(),amount: anyPositiveDouble()])}response {status 201body([status: "SUCCESS",transactionId: regex('[0-9a-f]{8}-[0-9a-f]{4}')])}
}

消費方(測試中使用Stub):

@SpringBootTest
@AutoConfigureStubRunner(ids = "com.example:payment-service:+:stubs")
class OrderServiceContractTest {@Testvoid shouldProcessPayment() {PaymentResult result = paymentClient.charge(new PaymentRequest(...));assertThat(result.getStatus()).isEqualTo("SUCCESS");}
}

五、架構師的最佳實踐建議

  1. 分層使用策略

    • 單元測試:80% Mock + 20% Stub
    • 集成測試:20% Mock + 80% Stub
    • 契約測試:100% Stub(基于提供方契約)
  2. 性能優化

    // 重用Mock對象提升測試速度
    @MockitoSettings(strictness = Strictness.LENIENT)
    public class ReusableMocksTest {@Mock static DatabaseConnection sharedConnection;
    }
    
  3. 反模式警示

    • ? 過度驗證:verify(mock, times(3)).trivialMethod()
    • ? Mock傳遞:when(mockA.call()).thenReturn(mockB)
    • ? 脆弱的Stub:硬編碼不合理的測試數據
  4. 現代替代方案

    • 虛擬服務(Testcontainers):代替Stub提供更真實的模擬
    @Container
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15");
    
    • 代碼生成Stub(OpenAPI Generator):基于API規范自動生成

六、架構決策樹

graph TDA[需要測試什么?] A --> B{驗證對象交互?}B -->|是| C[使用Mock]B -->|否| D{需要控制依賴行為?}D -->|是| E[使用Stub]D -->|否| F[使用真實對象]C --> G{需要部分真實行為?}G -->|是| H[使用Spy]G -->|否| I[使用純Mock]E --> J{跨服務邊界?}J -->|是| K[使用契約測試Stub]J -->|否| L[使用簡單Stub實現]

作為系統架構師,我建議:在保證測試質量的前提下選擇最簡單的模擬方案。Mock適合驗證內部協作,Stub適合隔離外部依賴,契約測試Stub則是微服務架構的必備工具。正確使用這些技術可以構建快速、可靠且維護成本低的測試體系。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/92519.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/92519.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/92519.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

香港服務器容器網絡插件的多節點通信性能基準測試

香港服務器容器網絡插件的多節點通信性能基準測試在云計算和容器化技術快速發展的今天&#xff0c;香港服務器因其優越的地理位置和網絡環境&#xff0c;成為眾多企業部署容器服務的首選。本文將深入探討香港服務器環境下容器網絡插件的多節點通信性能&#xff0c;通過詳實的基…

Vue3 學習教程,從入門到精通,Vue 3 全局 API 語法知識點及案例詳解(32)

Vue 3 全局 API 語法知識點及案例詳解 Vue 3 提供了豐富的全局 API&#xff0c;用于創建應用實例、注冊全局組件、指令、插件等。以下將詳細介紹 Vue 3 的主要全局 API&#xff0c;并結合詳細的案例代碼進行說明。每個案例代碼都包含中文注釋&#xff0c;幫助初學者更好地理解…

UE5多人MOBA+GAS 41、制作一個飛彈,添加準心索敵

文章目錄添加新角色&#xff08;不寫了&#xff09;創建一個發射技能創建一個飛彈類添加擊中特效添加準星UI獲取瞄準目標添加新角色&#xff08;不寫了&#xff09; 將原本的機器人藍圖改為BP_PlayerCharacter&#xff0c;以此創建子藍圖 創建動畫藍圖模板&#xff08;具體就…

解決渲染抖動與滾動錨點定位不準確問題的方法與經驗分享

場景描述&#xff1a;React 虛擬列表&#xff08;Virtualized List&#xff09;是當我們在處理大列表時&#xff0c;為了提升性能而采用的一種技術。然而在實現過程中&#xff0c;可能會遇到渲染抖動問題以及滾動錨點定位不準確的問題。??解決方案&#xff1a;React虛擬列表實…

OpenAI 時隔多年再開源!GPT-OSS 120B/20B 發布,支持本地部署,消費級 GPU 即可運行

OpenAI 近期做出了一項令人矚目的戰略轉變&#xff1a;宣布推出兩款開放權重&#xff08;Open Weight&#xff09; 語言模型 GPT-OSS-120B 和 GPT-OSS-20B。這不僅是其自 GPT-2 之后首次開源模型&#xff0c;更關鍵的是&#xff0c;這兩款模型特別針對消費級硬件進行了深度優化…

MySQL高可用方案之MySQL Group Replication高可用架構搭建完全指南

MySQL Group Replication高可用架構搭建完全指南 前言 在當今互聯網應用中,數據庫高可用性已成為系統設計的核心需求。MySQL作為最流行的開源關系型數據庫之一,其高可用解決方案備受關注。MySQL Group Replication是MySQL官方推出的原生高可用解決方案,它基于Paxos協議實現…

網站SSL證書到期如何更換?簡單完整操作指南

----------------------------------------------------------------------------------------------- 這是我在我的網站中截取的文章&#xff0c;有更多的文章歡迎來訪問我自己的博客網站rn.berlinlian.cn&#xff0c;這里還有很多有關計算機的知識&#xff0c;歡迎進行留言或…

Spring Boot 開發三板斧:POM 依賴、注解與配置管理

引言 Spring Boot 是一個功能強大且廣受歡迎的框架&#xff0c;用于快速構建基于 Spring 的應用。它通過簡化配置和自動化管理&#xff0c;幫助開發者專注于業務邏輯的實現。然而&#xff0c;要想高效地開發 Spring Boot 應用&#xff0c;掌握以下三個關鍵點至關重要&#xff1…

kubernetes安裝搭建

個人博客站—運維鹿:http://www.kervin24.top/ CSDN博客—做個超努力的小奚&#xff1a; https://blog.csdn.net/qq_52914969?typeblog 一、kubernetes介紹 Kubernetes本質是一組服務器集群&#xff0c;它可以在集群的每個節點上運行特定的程序&#xff0c;來對節點中的容…

MySQL高可用方案之MySQL InnoDB Cluster高可用架構實戰指南:從零搭建到生產部署

MySQL InnoDB Cluster高可用架構實戰指南:從零搭建到生產部署 一、引言:為什么選擇MySQL InnoDB Cluster 在當今數據驅動的商業環境中,數據庫高可用性已成為企業IT基礎設施的核心需求。MySQL作為全球最受歡迎的開源關系型數據庫,其高可用解決方案備受關注。而MySQL InnoD…

祝融號無線電工作頻段

前面深入查證了旅行者1號的無線電工作頻段&#xff1a; 旅行者1號無線電工作頻段-CSDN博客 下面嘗試查證我國祝融號無線電工作頻段。 一、百度百科 來自百度百科&#xff1a; 我注意到一條關鍵信息&#xff1a; 這說明祝融號在國際上是有合作的&#xff0c;而不是我們國家單…

Kafka生產者相關原理

前言前面已經介紹了Kafka的架構知識并引出了Kafka的相關專業名稱進行解釋這次分享一下Kafka對生產者發送消息進行處理的運行機制和原理生產者發送消息兩種方式同步發送消息程序中線程執行完消息發送操作之后會等待Kafka的消息回應ack默認等待30秒沒有回應就會拋出異常等待時間和…

Python 獲取對象信息的所有方法

在 Python 里&#xff0c;我們經常需要檢查一個對象的類型、屬性、方法&#xff0c;甚至它的源碼。這對調試、學習和動態編程特別有用。今天我們就來聊聊獲取對象信息的常見方法&#xff0c;按由淺入深的順序來學習。 參考文章&#xff1a;Python 獲取對象信息 | 簡單一點學習…

vuhub Beelzebub靶場攻略

靶場下載&#xff1a; 下載地址&#xff1a;https://download.vulnhub.com/beelzebub/Beelzebub.zip 靶場攻略&#xff1a; 主機發現&#xff1a; nmap 192.168.163.1/24 端口掃描&#xff1a; nmap -p-65535 -A 192.168.163.152 發現沒有額外端口。 頁面掃描&#xff1…

開啟單片機

前言&#xff1a;為未來拼搏的第n天&#xff0c;從單片機開始。為什么要學習單片機呢&#xff0c;單片機的工作涉及范圍及其廣如&#xff1a;消費電子&#xff0c;游戲機音響&#xff1b;工業控制&#xff1a;機器人控制&#xff1b;醫療設備&#xff0c;通信設備&#xff0c;物…

人工智能系列(8)如何實現無監督學習聚類(使用競爭學習)?

案例&#xff1a;鳶尾花數據集的聚類一.聚類簡介神經網絡能夠從輸入數據中自動提取有意義的特征&#xff0c;而競爭學習規則使得單層神經網絡能夠根據相似度將輸入樣本進行聚類&#xff0c;每個聚類由一個輸出神經元代表并作為該類別的“原型”&#xff0c;從而實現對輸入模式的…

Windows安裝mamba全流程(全網最穩定最成功)

windows系統下安裝mamba會遇到各種各樣的問題。博主試了好幾天&#xff0c;把能踩的坑都踩了&#xff0c;總結出了在windows下安裝mamba的一套方法&#xff0c;已經給實驗室的windows服務器都裝上了。只要跟著我的流程走下來&#xff0c;大概率不會出問題&#xff0c;如果遇到其…

Autosar Dem配置-最大存儲的DTC信息個數配置-基于ETAS軟件

文章目錄 前言 Autosar Dem相關配置 ETAS工具中的配置 生成文件分析 測試驗證 總結 前言 診斷DTC開發中,會有故障快照和擴展數據的存儲需求,但由于控制器的可用存儲空間有限,所以無法存儲所有DTC的信息,這時就需要限制存儲的數量,本文介紹該參數在ETAS軟件中的配置。 Au…

【MySQL】EXISTS 與 NOT EXISTS 深度解析:從原理到實戰的完整指南

在復雜的業務查詢中&#xff0c;我們常常需要判斷“是否存在滿足某條件的記錄”或“找出不滿足某些條件的記錄”。這時&#xff0c;EXISTS 和 NOT EXISTS 子查詢便成為強大的工具。它們不僅邏輯清晰、語義明確&#xff0c;而且在某些場景下性能遠超 IN 或 JOIN。然而&#xff0…

面對信號在時頻平面打結,VNCMD分割算法深度解密

“ 信號迷宮中的破壁者&#xff1a;VNCMD如何分解糾纏的時空密碼&#xff1f;——從鯨歌到機械故障&#xff0c;寬帶信號分解新紀元。”01—痛點直擊&#xff1a;為什么傳統方法集體失效&#xff1f;2017年&#xff0c;上海交大團隊提出了一項突破性研究&#xff1a;變分非線性…