当前位置: 首页 > news >正文

Spring Boot 单元测试:@SpyBean 使用教程

Spring Boot 单元测试:@SpyBean 使用教程

1. 什么是 @SpyBean

@SpyBean 是 Spring Boot Test 提供的一个注解,用于在单元测试中**部分模拟(Partial Mock)**一个 Spring Bean。它类似于 Mockito 的 @Spy,但专门用于 Spring 容器中的 Bean。

  • @MockBean:完全模拟一个 Bean,所有方法都需要手动定义行为。
  • @SpyBean:基于真实 Bean,只重写(Mock)部分方法,其余方法仍然调用真实逻辑。

2. 何时使用 @SpyBean

适用场景

  • 你只想修改某个 Bean 的某个方法,但其他方法仍然走真实逻辑。
  • 你希望测试依赖某个 Bean 的真实逻辑,但需要控制其中某个方法的返回值。

不适用场景

  • 需要完全模拟整个 Bean(用 @MockBean)。
  • Bean 的方法是 finalstatic(Mockito 无法 Spy final 方法)。

3. 基本用法

示例场景

假设有一个 UserService 依赖 UserRepository,我们想测试 UserService,但只重写 UserRepositoryfindById() 方法,其他方法(如 save())仍然走真实逻辑。

@Service
public class UserService {@Autowiredprivate UserRepository userRepository;public String getUserName(Long id) {User user = userRepository.findById(id).orElseThrow();return user.getName();}
}

测试代码

@SpringBootTest
public class UserServiceTest {@Autowiredprivate UserService userService;@SpyBean  // 对 UserRepository 进行 Spy,未 Mock 的方法仍然走真实逻辑private UserRepository userRepository;@Testpublic void testGetUserName() {// 准备测试数据User mockUser = new User(1L, "Alice");userRepository.save(mockUser);  // 真实调用 save()// 只 Mock findById(),让它返回自定义数据doReturn(Optional.of(new User(1L, "Mocked Alice"))).when(userRepository).findById(1L);// 调用测试方法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();// 带参数匹配
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()(显式调用真实方法)

// 默认会走真实方法,但也可以显式声明
doCallRealMethod().when(mySpyBean).someMethod();

5. @SpyBean vs @MockBean

特性@SpyBean@MockBean
默认行为未 Mock 的方法调用真实逻辑未 Mock 的方法返回默认值(null/0/false)
适用场景只修改部分方法,其他方法仍需真实逻辑完全模拟 Bean,不依赖真实实现
性能稍慢(需代理真实对象)更快(纯 Mock 对象)

6. 常见问题

Q1: @SpyBean 能用于 final 方法吗?

不能! Mockito 无法 Spy final 方法。如果遇到 final 方法,考虑:

  • 改用 @MockBean 完全模拟。
  • 重构代码,避免 final 方法。

Q2: @SpyBean@Spy 的区别?

  • @Spy 是 Mockito 提供的,用于普通对象。
  • @SpyBean 是 Spring Boot 提供的,用于 Spring Bean。

Q3: 如何验证方法调用次数?

// 验证 someMethod 被调用 1 次
verify(mySpyBean, times(1)).someMethod();

7. 总结

  • @SpyBean 适合部分 Mock,只修改某些方法,其余方法仍然走真实逻辑。
  • 常用方式
    • doReturn().when(spy).method():返回固定值。
    • doAnswer():自定义逻辑。
    • doThrow():模拟异常。
  • 不要用于 final 方法

🚀 现在你可以在 Spring Boot 测试中灵活使用 @SpyBean 了! 如果有问题,欢迎讨论!

http://www.dtcms.com/a/325674.html

相关文章:

  • Linux生成自签名 SSL 证书(适用于测试或内部使用)
  • CI/CD渗透测试靶场
  • cesium/resium 修改子模型材质
  • [Oracle] UNPIVOT 列转行
  • MySQL 数据操作全流程:创建、读取、更新与删除实战
  • openEuler、 CentOS、Ubuntu等 Linux 系统中,Docker 常用命令总结
  • FPGA+护理:跨学科发展的探索(一)
  • SAE J2716多协议网关的硬件架构与实时协议转换机制解析
  • 三种常见的菜单路由封装方式详解
  • rust编译过程的中间表现形式如何查看,ast,hir,mir
  • Rust学习笔记(一)|Rust初体验 猜数游戏
  • Excel 实战:基因表达矩阵前处理中测序符号的快速剥离方法
  • K210人脸识别系统
  • 在Linux中部署tomcat
  • 【Redis的安装与配置】
  • 如何理解Tomcat、Servlet、Catanalina的关系
  • 从零开始的云计算生活——第四十一天,勇攀高峰,Kubernetes模块之单Master集群部署
  • 微美全息(NASDAQ:WIMI)Raft携手节点动态评估:引领联盟链高性能共识新潮流
  • 为 Promethus 配置https访问
  • 机器学习 - Kaggle项目实践(1)Titanic
  • 揭开内容分发网络(CDN)的神秘面纱:互联网的隐形加速器
  • 飞翔的小鸟
  • 【数据结构入门】二叉树(1)
  • day23|前端学习三件套
  • 了解不同电磁仿真类型中的电容报告
  • 数学建模——灰色预测(GM11)
  • YOLO性能评估指标详细总结
  • Linux中DHCP配置指南指南(配实验步骤与注释)
  • 19.Linux DHCP服务
  • 108-基于Python的中国古诗词数据可视化分析系统