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

发布于:2025-08-20 ⋅ 阅读:(18) ⋅ 点赞:(0)

一、JUnit 简介

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

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

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

二、环境准备

2.1 依赖配置

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

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

这个依赖包中已经包含了 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 等工具,可以编写出高效、可维护的测试代码,从而提高软件质量和开发效率。


网站公告

今日签到

点亮在社区的每一天
去签到