Spring Boot 利用 单元测试(JUnit )教程

一、JUnit 简介

JUnit 是一款优秀的开源 Java 单元测试框架,也是目前使用率最高最流行的测试框架。它主要用于白盒测试和回归测试:

  • ​白盒测试​​:把测试对象看作一个打开的盒子,程序内部的逻辑结构和其他信息对测试人员是公开的
  • ​回归测试​​:软件或环境修复或更正后的再测试
  • ​单元测试​​:最小粒度的测试,以测试某个功能或代码块,一般由程序员来做

Spring Boot 默认已经集成了 JUnit 框架支持,开发工具如 Eclipse 和 IDEA 对 JUnit 都有很好的支持。

二、环境准备

2.1 依赖配置

对于 Spring Boot 项目,默认的 spring-boot-starter-test 依赖已经包含了 JUnit 支持:

org.springframework.boot
spring-boot-starter-test
test

这个依赖包中已经包含了 JUnit 5(JUnit Jupiter)、Mockito 和 AssertJ 等测试工具。

三、JUnit 4 与 JUnit 5

3.1 JUnit 4 基础使用

Spring Boot 2.x 早期版本默认使用 JUnit 4,典型的测试类结构如下:

@RunWith(SpringRunner.class)
@SpringBootTest
public class SimpleTest {
@Test
public void doTest() {
int num = new Integer(1);
Assert.assertEquals(num, 1);
}
}

​常用注解​​:

  • @RunWith(SpringRunner.class):标识为 JUnit 的运行环境
  • @SpringBootTest:获取启动类、加载配置,确定装载 Spring Boot
  • @Test:声明需要测试的方法
  • @BeforeClass:针对所有测试,只执行一次,且必须为 static void
  • @AfterClass:针对所有测试,只执行一次,且必须为 static void
  • @Before:每个测试方法前都会执行的方法
  • @After:每个测试方法后都会执行的方法
  • @Ignore:忽略方法

​断言方法​​:

  • Assert.assertEquals:对比两个值相等
  • Assert.assertNotEquals:对比两个值不相等
  • Assert.assertSame:对比两个对象的引用相等
  • Assert.assertArrayEquals:对比两个数组相等
  • Assert.assertTrue:验证返回是否为真
  • Assert.assertFalse:验证返回是否为假
  • Assert.assertNull:验证 null
  • Assert.assertNotNull:验证非 null

​超时测试​​:

@Test(timeout = 1000) // 时间单位为毫秒

3.2 JUnit 5 基础使用

JUnit 5 是 JUnit 测试框架的最新版本,由三个主要模块组成:

  • ​JUnit Platform​​:提供了测试执行的基础设施
  • ​JUnit Jupiter​​:提供了新的编程模型和扩展模型
  • ​JUnit Vintage​​:支持运行 JUnit 3 和 JUnit 4 的测试用例

JUnit 5 引入了许多新特性,例如嵌套测试、参数化测试、动态测试等。

​典型测试类结构​​:

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import static org.junit.jupiter.api.Assertions.assertEquals;
@SpringBootTest
public class MyServiceTest {
@Test
public void testSomething() {
// 测试逻辑
assertEquals(2, 1 + 1);
}
}

​常用注解​​:

  • @Test:声明需要测试的方法
  • @BeforeEach:每个测试方法前都会执行的方法(相当于 JUnit 4 的 @Before)
  • @AfterEach:每个测试方法后都会执行的方法(相当于 JUnit 4 的 @After)
  • @BeforeAll:针对所有测试,只执行一次,且必须为 static void(相当于 JUnit 4 的 @BeforeClass)
  • @AfterAll:针对所有测试,只执行一次,且必须为 static void(相当于 JUnit 4 的 @AfterClass)
  • @Disabled:忽略方法(相当于 JUnit 4 的 @Ignore)

​断言方法​​:
JUnit 5 提供了丰富的断言方法,例如 assertEqualsassertTrue 等。此外,还可以使用 AssertJ 库提供更流畅的断言语法。

四、Spring Boot 集成 JUnit 5 实践

4.1 测试类基本结构

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import static org.junit.jupiter.api.Assertions.assertEquals;
@SpringBootTest
public class UserServiceTest {
@Test
public void testGetUserById() {
// 假设这里有一个 UserService 实例
// User user = userService.getUserById(1L);
// assertEquals("John Doe", user.getName());
assertEquals(2, 1 + 1); // 示例断言
}
}

4.2 使用 Mockito 进行模拟测试

在单元测试中,我们通常需要模拟外部依赖。Mockito 是一个流行的模拟框架,可以与 JUnit 5 无缝集成。

import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.boot.test.context.SpringBootTest;
import static org.mockito.Mockito.when;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Optional;
@SpringBootTest
public class OrderServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private OrderService orderService;
@Test
public void testCreateOrder() {
User user = new User(1L, "John Doe");
when(userRepository.findById(1L)).thenReturn(Optional.of(user));
Order order = orderService.createOrder(1L, "Laptop");
assertEquals("John Doe", order.getUser().getName());
}
}

4.3 使用 AssertJ 进行流畅断言

AssertJ 提供了更流畅的断言语法:

import static org.assertj.core.api.Assertions.assertThat;
@Test
public void testAssertJ() {
String result = myService.processData();
assertThat(result).isEqualTo("Expected Result");
assertThat(result).contains("Expected");
assertThat(result).startsWith("E");
assertThat(result).isNotEmpty();
}

五、测试类型

5.1 单元测试

单元测试是最小粒度的测试,测试单个类或方法。通常使用 Mockito 来模拟依赖项。

5.2 集成测试

集成测试用于测试多个组件如何协同工作。使用 @SpringBootTest 注解加载完整的 Spring 应用上下文。

@SpringBootTest
public class IntegrationTest {
@Autowired
private MyService myService;
@Test
public void testIntegration() {
// 测试多个组件的集成
}
}

5.3 切片测试

切片测试是介于单元测试和集成测试之间的一种测试,只加载 Spring 应用上下文的一部分。

@WebMvcTest(MyController.class)
public class MyControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testController() throws Exception {
mockMvc.perform(get("/api/test"))
.andExpect(status().isOk());
}
}

六、测试最佳实践

  1. ​测试命名​​:使用描述性的测试方法名称,如 shouldReturnXWhenYGivenZ
  2. ​单一职责​​:每个测试方法应该只测试一个功能点
  3. ​AAA 模式​​:遵循 Arrange-Act-Assert 模式组织测试代码
  4. ​避免过度依赖​​:尽量使用模拟对象隔离被测代码
  5. ​测试覆盖率​​:追求有意义的测试覆盖率,而不仅仅是高数字
  6. ​持续集成​​:将测试作为持续集成流程的一部分

七、总结

Spring Boot 与 JUnit 的集成提供了强大的测试能力,无论是简单的单元测试还是复杂的集成测试都能很好地支持。JUnit 5 作为最新版本,提供了更多现代化特性,使测试更加灵活和强大。通过合理使用 Mockito、AssertJ 等工具,可以编写出高效、可维护的测试代码,从而提高软件质量和开发效率。

posted @ 2025-08-20 22:39  wzzkaifa  阅读(213)  评论(0)    收藏  举报