Java测试类中获取待测试类实例的最佳实践
Java测试类中获取待测试类实例的最佳实践
这得看你做的是单元测试还是集成测试——两种方式各有适用场景,不存在绝对的“最佳”,我给你拆解清楚:
一、手动实例化(new ClassToBeTested())
这种方式是单元测试的首选方案,优势和适用场景如下:
- 测试启动速度极快:不需要加载庞大的Spring上下文,几毫秒就能启动测试用例,适合频繁运行的单元测试。
- 完全控制依赖:你可以手动传入Mock对象(比如借助Mockito框架),把待测试类和外部依赖完全隔离,只聚焦测试目标类本身的业务逻辑,避免其他组件的干扰。
- 适合纯POJO或依赖简单的类:如果待测试类没有复杂的Spring管理依赖,手动实例化是最直接高效的方式。
举个典型的单元测试例子:
public class UserServiceTest { // Mock依赖的DAO层 private UserDao mockUserDao = Mockito.mock(UserDao.class); // 手动实例化待测试类,传入Mock依赖 private UserService userService = new UserService(mockUserDao); @Test public void testGetUserById() { // 预设Mock的返回值 Mockito.when(mockUserDao.getById(1L)).thenReturn(new User(1L, "Alice")); // 调用待测试方法 User result = userService.getUserById(1L); // 断言结果 Assert.assertEquals("Alice", result.getName()); } }
二、从Spring上下文获取(@Autowired + Spring测试注解)
这种方式更适合集成测试场景,适用情况包括:
- 需要验证多组件协同工作:比如你要测试Service调用Dao层操作数据库的完整流程,或者多个Spring Bean之间的交互逻辑,这时候需要Spring帮你注入所有真实的依赖。
- 依赖复杂的Spring组件:如果待测试类依赖数据库连接池、Redis客户端、消息队列等Spring管理的组件,手动实例化这些依赖成本极高,通过上下文注入更省心。
示例代码(Spring传统测试方式):
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"/services-test-config.xml"}) public class MyServiceTest { @Autowired private MyService service; @Test public void testServiceWithDbInteraction() { // 测试完整的服务流程,包括真实的数据库读写 User result = service.createUser(new User(null, "Bob")); Assert.assertNotNull(result.getId()); } }
注意:如果是Spring Boot项目,更推荐用@SpringBootTest代替@RunWith(SpringJUnit4ClassRunner.class),它的配置更简洁,还支持自动扫描配置类、嵌入式容器等特性。
总结一下最佳实践
- 优先用手动实例化+Mock依赖做单元测试,保证测试的速度、隔离性和精准性,聚焦单个类的逻辑正确性。
- 当需要验证多组件协同、外部资源(数据库、缓存等)交互时,再用Spring上下文注入做集成测试。
- 不要用Spring上下文来做简单的单元测试——启动慢、依赖多,完全没必要。
内容的提问来源于stack exchange,提问作者Julien Berthoud




