SpringBoot JUnit 教程

1. 核心依赖 (Maven)

XML 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

该 Starter 自动引入:

  • JUnit 5 (Jupiter)

  • Mockito

  • AssertJ

  • Spring Test 等


2. 基础注解

注解 作用
@SpringBootTest 启动完整 Spring 上下文(集成测试)
@Test 标记测试方法
@BeforeEach / @AfterEach 每个测试前/后执行
@BeforeAll / @AfterAll 所有测试前/后执行(需静态方法)
@DisplayName 给测试起中文名
@Disabled 禁用测试

3. 单元测试(Service 层)

被测 Service:

java 复制代码
@Service
public class UserService {
    public String getUserName(Long id) {
        return "user-" + id;
    }
}

测试类:

java 复制代码
@SpringBootTest
class UserServiceTest {

    @Autowired
    private UserService userService;

    @Test
    @DisplayName("根据ID获取用户名")
    void testGetUserName() {
        String name = userService.getUserName(1L);
        assertEquals("user-1", name);
        assertNotNull(name);
    }
}

4. Web 层测试(Controller)

使用 @WebMvcTest 只加载 Web 层,比 @SpringBootTest 轻量。

被测 Controller:

java 复制代码
@RestController
@RequestMapping("/api/users")
public class UserController {
    @GetMapping("/{id}")
    public String getUser(@PathVariable Long id) {
        return "user-" + id;
    }
}

测试类:

java 复制代码
@WebMvcTest(UserController.class)
class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    void testGetUser() throws Exception {
        mockMvc.perform(get("/api/users/1"))
               .andExpect(status().isOk())
               .andExpect(content().string("user-1"));
    }
}

5. Mock 依赖(隔离测试)

使用 @MockBean 模拟 Service,避免依赖真实数据库。

java 复制代码
@SpringBootTest
class UserControllerMockTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;

    @Test
    void testGetUser() throws Exception {
        when(userService.getUserName(1L)).thenReturn("mock-user");

        mockMvc.perform(get("/api/users/1"))
               .andExpect(status().isOk())
               .andExpect(content().string("mock-user"));
    }
}

6. 数据层测试(Repository)

使用 @DataJpaTest 测试 JPA,默认回滚事务。

java 复制代码
@DataJpaTest
class UserRepositoryTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    void testSaveAndFind() {
        User user = new User("test");
        userRepository.save(user);

        Optional<User> found = userRepository.findByName("test");
        assertTrue(found.isPresent());
    }
}

7. 断言进阶(AssertJ)

java 复制代码
import static org.assertj.core.api.Assertions.*;

assertThat(user.getName()).startsWith("user");
assertThat(list).hasSize(3).contains("a", "b");

8. 测试生命周期

java 复制代码
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class LifecycleTest {
    @BeforeAll
    void initAll() { /* 无需 static */ }
}

9. 常用 Mockito 操作

java 复制代码
// 验证调用次数
verify(userService, times(1)).getUserName(anyLong());

// 抛出异常
when(userService.getUserName(1L)).thenThrow(new RuntimeException("error"));

// 参数匹配
when(userService.getUserName(eq(1L))).thenReturn("user-1");

10. 测试覆盖率 (Jacoco)

java 复制代码
<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.11</version>
</plugin>

执行 mvn clean test 后生成 target/site/jacoco/index.html。


11. 最佳实践总结

类型 推荐注解 说明
单元测试(Service) @SpringBootTest 可配合 @MockBean
Web 层测试 @WebMvcTest 只加载 Controller
Repository 测试 @DataJpaTest 轻量,自动回滚
集成测试 @SpringBootTest 加载完整上下文
测试命名 should_xxx_when_xxx 清晰表达意图
断言 AssertJ 更丰富流畅

12. 面试常见问题

  1. @SpringBootTest 和 @WebMvcTest 区别?

    • @SpringBootTest:加载全部 Bean,适合集成测试。

    • @WebMvcTest:只加载 Web 层,更快。

  2. @MockBean 和 @Mock 区别?

    • @MockBean 是 Spring 提供的,会将 Mock 对象注入 Spring 容器。

    • @Mock 是 Mockito 的,不管理容器。

  3. 如何测试异步方法?

    使用 @Async + CountDownLatch 或 CompletableFuture 配合 await()。

相关推荐
这个DBA有点耶1 小时前
从症状到根因:数据库监控指标的分层方法与静态/动态阈值策略
数据库·mysql·代码规范
SelectDB1 小时前
时间旅行与快照能力速查:Doris 侧三条落地路径
大数据·数据库·数据分析
SelectDB2 小时前
云数仓成本结构拆解速查:五层计费 vs Doris / 托管形态
大数据·数据库·数据分析
SelectDB2 小时前
什么场景能承接与建议保留:Doris vs Snowflake 边界速查
大数据·数据库·数据分析
这个DBA有点耶4 小时前
DELETE没删多少数据,表却越来越大——InnoDB删除空洞与页合并失效的根因
数据库·mysql·代码规范
ly76897 小时前
PostgreSQL 备份恢复策略:pg_basebackup、WAL 归档与 PITR 在企业 Java 系统中的落地
java·数据库·postgresql·pitr·pg_basebackup·wal 归档
流烟默7 小时前
SSE 实战:在 SpringBoot + Vue 项目中零依赖实现轻量级实时消息推送
vue.js·spring boot·后端·sse
小羊没烦恼!7 小时前
Ajax与JSON的一些总结
android·java·前端·数据库·mysql·算法·okhttp
注塑机数据采集联网8 小时前
如何解决注塑机数据采集联网对接MES系统数据WiFi传输数据不稳问题
大数据·数据库·物联网·数据挖掘·数据分析