java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot @SpyBean

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

作者:zru_9602

本文主要介绍了SpringBoot单元测试中@SpyBean使用小结,@SpyBean用于部分模拟SpringBean,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1. 什么是@SpyBean?

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

2. 何时使用@SpyBean?

适用场景

不适用场景

3. 基本用法

示例场景

假设有一个 UserService 依赖 UserRepository,我们想测试 UserService,但只重写 UserRepositoryfindById() 方法,其他方法(如 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() {
        // 准备测试数据
        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.@SpyBeanvs@MockBean

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

6. 常见问题

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

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

Q2:@SpyBean和@Spy的区别?

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

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

7. 总结

到此这篇关于SpringBoot单元测试中@SpyBean使用小结的文章就介绍到这了,更多相关SpringBoot @SpyBean内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文