您现在的位置是:首页 >技术杂谈 >Spring Test 教程大纲网站首页技术杂谈

Spring Test 教程大纲

不听话的小耳朵 2025-03-25 12:01:01
简介Spring Test 教程大纲

Spring Test 教程大纲

目标:基于 JUnit 5,系统学习 Spring Test 的核心原理、注解使用、测试框架集成及扩展开发。


第 1 章:Spring Test 简介与核心原理

1.1 Spring Test 的作用与优势

  • 简化 Spring 应用的单元测试与集成测试。
  • 核心目标:上下文管理、依赖注入、事务控制、环境隔离。
  • 与普通 JUnit 测试的区别(自动注入、上下文复用)。

1.2 TestContext 框架核心机制

  • 上下文缓存:避免重复加载 ApplicationContext
  • 依赖注入:将 Spring Bean 注入测试类(@Autowired)。
  • 事务管理:默认回滚机制(@Transactional)。
  • 与 JUnit 5 集成:通过 SpringExtension 扩展。

1.3 测试生命周期与流程

  1. 加载 ApplicationContext
  2. 注入测试类依赖。
  3. 执行测试方法(事务管理)。
  4. 销毁或复用上下文。

第 2 章:Spring Test 基础用法

2.1 环境配置与测试类编写

  1. 启用 Spring Test
    @ExtendWith(SpringExtension.class) // JUnit 5 扩展  
    @ContextConfiguration(classes = AppConfig.class) // 指定配置  
    public class MyServiceTest { ... }  
    
  2. 注入依赖
    @Autowired  
    private UserService userService;  
    

2.2 事务管理

  • 默认行为:测试方法结束后事务回滚。
  • 控制事务提交与回滚
    @Test  
    @Transactional  
    @Rollback(false) // 提交事务  
    public void testSaveUser() { ... }  
    

2.3 上下文管理与重置

  • 强制重置上下文
    @Test  
    @DirtiesContext(methodMode = AFTER_METHOD) // 方法结束后重置  
    public void testModifySharedState() { ... }  
    

第 3 章:核心注解详解

3.1 基础配置注解

注解作用
@ContextConfiguration指定配置文件或配置类(XML、Java Config)。
@TestPropertySource加载测试专用属性文件(覆盖主配置)。
@ActiveProfiles激活特定环境 Profile(如 "test")。

3.2 事务控制注解

注解作用
@Transactional在测试方法中启用事务,默认回滚。
@Rollback显式控制事务是否回滚(true 回滚,false 提交)。
@Commit等效于 @Rollback(false)

3.3 测试数据与初始化

  • 使用 @Sql 初始化数据库
    @Test  
    @Sql(scripts = "classpath:init-data.sql") // 执行 SQL 脚本  
    public void testQueryData() { ... }  
    

3.4 动态属性注入(JUnit 5.8+)

@DynamicPropertySource  
static void setProperties(DynamicPropertyRegistry registry) {  
    registry.add("db.url", () -> "jdbc:h2:mem:test");  
}  

第 4 章:扩展接口与高级功能

4.1 自定义 TestExecutionListener

  • 监听测试生命周期:实现 TestExecutionListener 接口。
    public class CustomTestListener implements TestExecutionListener {  
        @Override  
        public void beforeTestMethod(TestContext testContext) {  
            System.out.println("Before test method: " + testContext.getTestMethod());  
        }  
    }  
    
  • 注册监听器
    @TestExecutionListeners(  
        listeners = CustomTestListener.class,  
        mergeMode = MergeMode.MERGE_WITH_DEFAULTS  
    )  
    public class CustomListenerTest { ... }  
    

4.2 自定义 ContextLoader

  • 扩展上下文加载逻辑:实现 ContextLoader 接口。
    public class CustomContextLoader implements ContextLoader {  
        @Override  
        public ApplicationContext loadContext(String... locations) {  
            // 自定义加载逻辑  
            return new AnnotationConfigApplicationContext(AppConfig.class);  
        }  
    }  
    
  • 使用自定义加载器
    @ContextConfiguration(loader = CustomContextLoader.class)  
    public class CustomLoaderTest { ... }  
    

第 5 章:实战场景与最佳实践

5.1 分层测试

  1. Service 层测试

    @ExtendWith(SpringExtension.class)  
    @ContextConfiguration(classes = ServiceTestConfig.class)  
    public class UserServiceTest {  
        @Autowired  
        private UserService userService;  
    
        @Test  
        public void testCreateUser() {  
            User user = userService.createUser("Alice");  
            assertNotNull(user.getId());  
        }  
    }  
    
  2. DAO 层测试

    @ExtendWith(SpringExtension.class)  
    @ContextConfiguration(classes = DaoTestConfig.class)  
    @Transactional  
    public class UserDaoTest {  
        @Autowired  
        private UserDao userDao;  
    
        @Test  
        @Sql(scripts = "classpath:test-data.sql")  
        public void testFindUser() {  
            User user = userDao.findById(1L);  
            assertEquals("Alice", user.getName());  
        }  
    }  
    
  3. Web 层测试(集成 MockMvc)

    @ExtendWith(SpringExtension.class)  
    @ContextConfiguration(classes = WebConfig.class)  
    @WebAppConfiguration // 启用 Web 上下文  
    public class UserControllerTest {  
        @Autowired  
        private WebApplicationContext context;  
        private MockMvc mockMvc;  
    
        @BeforeEach  
        void setup() {  
            mockMvc = MockMvcBuilders.webAppContextSetup(context).build();  
        }  
    
        @Test  
        void testGetUser() throws Exception {  
            mockMvc.perform(get("/user/1"))  
                   .andExpect(status().isOk())  
                   .andExpect(jsonPath("$.name").value("Alice"));  
        }  
    }  
    

5.2 依赖模拟(Mockito 集成)

  • 手动模拟依赖
    @TestConfiguration  
    static class MockConfig {  
        @Bean  
        public PaymentService paymentService() {  
            return Mockito.mock(PaymentService.class);  
        }  
    }  
    
    @ExtendWith(SpringExtension.class)  
    @ContextConfiguration(classes = {AppConfig.class, MockConfig.class})  
    public class OrderServiceTest {  
        @Autowired  
        private OrderService orderService;  
    
        @Autowired  
        private PaymentService paymentService;  
    
        @Test  
        public void testPlaceOrder() {  
            Mockito.when(paymentService.process(Mockito.any())).thenReturn(true);  
            boolean result = orderService.placeOrder(new Order());  
            assertTrue(result);  
        }  
    }  
    

第 6 章:优化与调试

6.1 性能优化

  • 复用上下文(避免频繁加载)。
  • 使用轻量级配置(如 H2 内存数据库)。

6.2 常见问题与调试

  • 上下文未加载:检查 @ContextConfiguration 路径或配置类。
  • 事务未回滚:确保 @Transactional@Rollback 正确配置。
  • 依赖注入失败:确认 Bean 是否被扫描到或手动注册。

附录:学习资源


通过本教程,学习者将掌握 Spring Test 的核心功能,并能够独立完成企业级 Spring 应用的测试开发。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。