SpringBoot單元測試中@SpyBean使用小結(jié)
1. 什么是@SpyBean?
@SpyBean 是 Spring Boot Test 提供的一個注解,用于在單元測試中**部分模擬(Partial Mock)**一個 Spring Bean。它類似于 Mockito 的 @Spy,但專門用于 Spring 容器中的 Bean。
- @MockBean:完全模擬一個 Bean,所有方法都需要手動定義行為。
- @SpyBean:基于真實 Bean,只重寫(Mock)部分方法,其余方法仍然調(diào)用真實邏輯。
2. 何時使用@SpyBean?
? 適用場景:
- 你只想修改某個 Bean 的某個方法,但其他方法仍然走真實邏輯。
- 你希望測試依賴某個 Bean 的真實邏輯,但需要控制其中某個方法的返回值。
? 不適用場景:
- 需要完全模擬整個 Bean(用
@MockBean)。 - Bean 的方法是
final或static(Mockito 無法 Spyfinal方法)。
3. 基本用法
示例場景
假設(shè)有一個 UserService 依賴 UserRepository,我們想測試 UserService,但只重寫 UserRepository 的 findById() 方法,其他方法(如 save())仍然走真實邏輯。
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public String getUserName(Long id) {
User user = userRepository.findById(id).orElseThrow();
return user.getName();
}
}
測試代碼
@SpringBootTest
public class UserServiceTest {
@Autowired
private UserService userService;
@SpyBean // 對 UserRepository 進行 Spy,未 Mock 的方法仍然走真實邏輯
private UserRepository userRepository;
@Test
public void testGetUserName() {
// 準備測試數(shù)據(jù)
User mockUser = new User(1L, "Alice");
userRepository.save(mockUser); // 真實調(diào)用 save()
// 只 Mock findById(),讓它返回自定義數(shù)據(jù)
doReturn(Optional.of(new User(1L, "Mocked Alice")))
.when(userRepository).findById(1L);
// 調(diào)用測試方法
String userName = userService.getUserName(1L);
// 驗證
assertEquals("Mocked Alice", userName);
// 其他方法仍然走真實邏輯
User savedUser = userRepository.findById(2L).orElse(null);
assertNull(savedUser); // 因為沒有存 ID=2 的用戶
}
}
4.@SpyBean的常用 Mock 方式
(1)doReturn().when(spy).method()
// 讓方法返回固定值
doReturn("Mocked Result").when(mySpyBean).someMethod();
// 帶參數(shù)匹配
doReturn("Hello").when(mySpyBean).greet(anyString());
(2)doAnswer()(自定義邏輯)
doAnswer(invocation -> {
String arg = invocation.getArgument(0);
return "Processed: " + arg;
}).when(mySpyBean).process(anyString());
(3)doThrow()(模擬異常)
doThrow(new RuntimeException("DB Error"))
.when(mySpyBean).save(any());
(4)doCallRealMethod()(顯式調(diào)用真實方法)
// 默認會走真實方法,但也可以顯式聲明 doCallRealMethod().when(mySpyBean).someMethod();
5.@SpyBeanvs@MockBean
| 特性 | @SpyBean | @MockBean |
|---|---|---|
| 默認行為 | 未 Mock 的方法調(diào)用真實邏輯 | 未 Mock 的方法返回默認值(null/0/false) |
| 適用場景 | 只修改部分方法,其他方法仍需真實邏輯 | 完全模擬 Bean,不依賴真實實現(xiàn) |
| 性能 | 稍慢(需代理真實對象) | 更快(純 Mock 對象) |
6. 常見問題
Q1:@SpyBean能用于final方法嗎?
? 不能! Mockito 無法 Spy final 方法。如果遇到 final 方法,考慮:
- 改用
@MockBean完全模擬。 - 重構(gòu)代碼,避免
final方法。
Q2:@SpyBean和@Spy的區(qū)別?
@Spy是 Mockito 提供的,用于普通對象。@SpyBean是 Spring Boot 提供的,用于 Spring Bean。
Q3: 如何驗證方法調(diào)用次數(shù)?
// 驗證 someMethod 被調(diào)用 1 次 verify(mySpyBean, times(1)).someMethod();
7. 總結(jié)
@SpyBean適合部分 Mock,只修改某些方法,其余方法仍然走真實邏輯。- 常用方式:
doReturn().when(spy).method():返回固定值。doAnswer():自定義邏輯。doThrow():模擬異常。
- 不要用于 final 方法。
到此這篇關(guān)于SpringBoot單元測試中@SpyBean使用小結(jié)的文章就介紹到這了,更多相關(guān)SpringBoot @SpyBean內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- springboot @ConditionalOnMissingBean注解的作用詳解
- SpringBoot 注解事務(wù)聲明式事務(wù)的方式
- springboot2中使用@JsonFormat注解不生效的解決
- SpringBoot中@Pattern注解對時間格式校驗方式
- springboot FeignClient注解及參數(shù)
- SpringBoot中@ConfigurationProperties注解的使用與源碼詳解
- SpringBoot2.0整合SpringCloud Finchley @hystrixcommand注解找不到解決方案
- 親測SpringBoot參數(shù)傳遞及@RequestBody注解---踩過的坑及解決
- 詳解SpringBoot 快速整合Mybatis(去XML化+注解進階)
相關(guān)文章
解決Maven項目pom.xml導入了Junit包還是用不了@Test注解問題
在Maven項目中,如果在非test目錄下使用@Test注解,可能會因為pom.xml中<scope>test</scope>的設(shè)置而無法使用,正確做法是將測試代碼放在src/test/java目錄下,或去除<scope>test</scope>限制,這樣可以確保Junit依賴正確加載并應(yīng)用于適當?shù)拇a部分2024-10-10
windows下vscode+vs2019開發(fā)JNI的示例
本文給大家普及windows下vscode+vs2019開發(fā)JNI的示例以及各個環(huán)節(jié)的注意事項,文章通過示例代碼圖文相結(jié)合給大家介紹的非常詳細,需要的朋友可以參考下2021-06-06
idea?maven項目不支持發(fā)行版本問題及解決過程
這段描述主要講解了解決Maven項目中JDK版本問題的方法,包括修改環(huán)境變量、配置IDEA編譯器版本以及調(diào)整pom.xml文件等內(nèi)容,通過這些步驟,可以有效解決項目運行中的兼容性問題2026-06-06
在js與java中判斷json數(shù)據(jù)中是否含有某字段的案例
這篇文章主要介紹了在js與java中判斷json數(shù)據(jù)中是否含有某字段的案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
Java ByteBuffer網(wǎng)絡(luò)編程用法實例解析
這篇文章主要介紹了Java ByteBuffer網(wǎng)絡(luò)編程用法實例解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-10-10
Spring boot 整合CXF開發(fā)web service示例
這篇文章主要介紹了Spring boot 整合CXF開發(fā)web service示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-05-05
使用Spring Cloud Feign作為HTTP客戶端調(diào)用遠程HTTP服務(wù)的方法(推薦)
在Spring Cloud中使用Feign, 我們可以做到使用HTTP請求遠程服務(wù)時能與調(diào)用本地方法一樣的編碼體驗,開發(fā)者完全感知不到這是遠程方法,更感知不到這是個HTTP請求,具體內(nèi)容詳情大家參考下本文2018-01-01

