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 + CountDownLatchCompletableFuture 配合 await()

相关推荐
hdsoft_huge2 小时前
SpringBoot系列06:RESTful接口开发,请求参数接收、全局跨域CORS完整配置
java·spring boot
AC赳赳老秦3 小时前
采购专员自动化:OpenClaw 自动比价、生成询价单、跟踪供应商报价进度实战指南
开发语言·数据库·人工智能·python·自动化·github·openclaw
C++ 老炮儿的技术栈3 小时前
MFC 自定义纯色居中文字进度条控件
c语言·数据库·c++·windows·算法·c·visual studio
灯澜忆梦3 小时前
【MySQL1】| DDL 数据定义语言
数据库·sql·mysql
2601_963771373 小时前
Speeding Up Creative Agency Portfolios: A Performance Guide
前端·数据库·php
运维大师3 小时前
【安全与故障排查】03-【复盘】数据库被入侵:从发现到溯源全过程
数据库·安全·adb
Quincy_Freak5 小时前
银河麒麟 SQLite 实操:Excel 导入与 SQL 语法编辑功能详解摘要
数据库·arm·数据库管理·大数据分析·银河麒麟·aarch64·sqlitego
七夜zippoe5 小时前
OpenClaw 数据加密:敏感信息保护的完整方案
数据库·mysql·php·openclaw·敏感保护
Dovis(誓平步青云)5 小时前
《C/C+++ Boost 轻量级搜索引擎实战:架构流程、技术栈与工程落地指南——HTML文件的清洗(上篇)》
开发语言·数据库·c++·搜索引擎·开源
蚁库7 小时前
Oracle 12c + ASM + UDEV 实战教程:从磁盘规划到日常管理,10节视频完整通关
数据库·oracle