1. 概述
在本篇文章中,我们将探讨如何通过依赖注入的方式,将 Mockito 的 Mock 对象注入到 Spring Bean 中,用于单元测试。
在真实项目中,组件往往依赖外部系统(如数据库、远程服务等),为了保证测试的独立性,我们通常需要对这些依赖进行 Mock,从而专注于被测单元本身的逻辑。使用 Mock 是一种非常干净且有效的隔离手段。
2. Maven 依赖
我们需要以下 Maven 依赖来支持单元测试和 Mock 对象的创建:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.12.0</version>
</dependency>
本例使用 Spring Boot 进行演示,当然传统 Spring 项目也完全适用。
3. 编写测试
3.1. 业务逻辑
首先,我们创建一个简单的 Service 类,作为被依赖的服务:
@Service
public class NameService {
public String getUserName(String id) {
return "Real user name";
}
}
然后在另一个 Service 中注入它:
@Service
public class UserService {
private NameService nameService;
@Autowired
public UserService(NameService nameService) {
this.nameService = nameService;
}
public String getUserName(String id) {
return nameService.getUserName(id);
}
}
为避免逻辑干扰,这里无论传入什么 ID 都返回固定值。
我们还需要一个标准的 Spring Boot 启动类用于扫描和初始化 Bean:
@SpringBootApplication
public class MocksApplication {
public static void main(String[] args) {
SpringApplication.run(MocksApplication.class, args);
}
}
3.2. 测试逻辑
首先配置测试专用的 Spring 配置类:
@Profile("test")
@Configuration
public class NameServiceTestConfiguration {
@Bean
@Primary
public NameService nameService() {
return Mockito.mock(NameService.class);
}
}
@Profile("test")
:仅在test
环境激活时加载该配置。@Primary
:确保 Spring 优先使用这个 Mock 实例,而不是真实的 Bean。Mockito.mock(NameService.class)
:创建一个 NameService 的 Mock 对象。
接着编写单元测试类:
@ActiveProfiles("test")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MocksApplication.class)
public class UserServiceUnitTest {
@Autowired
private UserService userService;
@Autowired
private NameService nameService;
@Test
public void whenUserIdIsProvided_thenRetrievedNameIsCorrect() {
Mockito.when(nameService.getUserName("SomeId")).thenReturn("Mock user name");
String testName = userService.getUserName("SomeId");
Assert.assertEquals("Mock user name", testName);
}
}
✅ 关键点如下:
@ActiveProfiles("test")
:启用 test profile,激活 Mock 配置。@Autowired
注入真实的UserService
和 Mock 的NameService
。- 使用
Mockito.when(...).thenReturn(...)
设置 Mock 行为。 - 最后验证调用结果是否符合预期。
⚠️ 也可以不使用 Profile 来实现 Mock 注入,但不推荐:
- 移除
@Profile
和@ActiveProfiles
。 - 添加
@ContextConfiguration(classes = NameServiceTestConfiguration.class)
到测试类上。
但这样容易污染全局配置,踩坑风险较高。
4. 总结
本文展示了如何简单粗暴地将 Mockito Mock 对象注入到 Spring Bean 中,实现干净的单元测试隔离。
所有示例代码均可在 GitHub 获取。