开发者

SpringBoot单元测试中@SpyBean使用小结

目录
  • 1. 什么是@SpyBean?
  • 2. 何时使用@SpyBean?
  • 3. 基本用法
    • 示例场景
    • 测试代码
  • 4.@SpyBean的常用 Mock 方式
    • (1)doReturn().when(spy).method()
    • (2)doAnswer()(自定义逻辑)
    • (3)doThrow()(模拟异常)
    • (4)doCallRealMethod()(显式调用真实方法)
  • 5.@SpyBeanvs@MockBean
    • 6. 常见问题
      • Q1:@SpyBean能用于final方法吗?
      • Q2:@SpyBean和@Spy的区别?
      • Q3: 如何验证方法调用次数?
    • 7. 总结

      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 {
          @Autowired
          private UserRepository userRe编程pository;
      
          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() {
              // 准备测试数据
              User mockUser = new User(1L, "Alice");
              userRepository.save(mockUser);  // 真实调用 save()
      
              // 只 Mock findById(),让它返回自定义数据
              doReturn(Optional.of(new User(1L, "Mocked Alice")))
                  .when(userhttp://www.devze.comRepository).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()(显式调用真实方法mJjpbALnS)

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

      5.@SpyBeanvs@MockBean

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

      6. 常见问题

      http://www.devze.com

      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 方法。

      到此这篇关于SpringBoot单元测试中@SpyBean使用小结的文章就介绍到这了,更多相关SpringBoot @SpyBean内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

      0

      上一篇:

      下一篇:

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      最新开发

      开发排行榜