首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >SpringBoot基础(五):集成JUnit5

SpringBoot基础(五):集成JUnit5

作者头像
Java微观世界
发布2025-01-20 21:10:24
发布2025-01-20 21:10:24
45900
代码可运行
举报
文章被收录于专栏:springbootspringboot
运行总次数:0
代码可运行

SpringBoot基础系列文章

SpringBoot基础(一):快速入门

SpringBoot基础(二):配置文件详解

SpringBoot基础(三):Logback日志

SpringBoot基础(四):bean的多种加载方式

SpringBoot基础(五):集成JUnit5

一、JUnit5介绍

JUnit5是一个功能强大的**单元测试**框架,是JUnit系列的最新版本,它引入了多个改进和新特性,旨在为Java应用程序提供灵活且模块化的测试支持。

1、JUnit5组成结构

  • JUnit Platform:这个模块提供了测试的**启动API和运行环境**,是整个JUnit5框架的核心。它支持在不同的环境中运行测试,如命令行、IDE或构建工具(例如Maven、Gradle)
  • JUnit Jupiter:这个模块包含了JUnit5的**新测试编写和扩展模型**,提供了全新的注解、测试方法和扩展机制
  • JUnit Vintage:为了支持旧版本的JUnit测试(JUnit3和JUnit4),JUnit5提供了Vintage模块。这个模块允许开发者继续运行以前版本的测试,同时过渡到JUnit5

2、什么是单元测试

  • 单元测试是指对软件中的**最小可测试单元**进行检查和验证的过程叫**单元测试**
  • 在**SpringBoot**中,最小可测试单元就是指**方法**

二、SpringBoot整合JUnit5

1、快速入门

  • SpringBoot版本从**2.2**以后,默认支持JUnit5
代码语言:javascript
代码运行次数:0
运行
复制
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
  • 测试类应放在**src/test/java**目录下
代码语言:javascript
代码运行次数:0
运行
复制
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class MySpringBootApplicationTests {

    @Test
    void contextLoads() {
        // 测试 Spring 应用上下文是否成功加载
    }
}

2、测试类和测试方法不需要声明为public

  • 在**JUnit4**中,测试类和测试方法**必须是public**的,因为JUnit4通过反射机制要求访问公共方法
  • 而**JUnit5**则没有这种要求,测试类和方法的可见性设为**包级(默认)**足够 JUnit 5 框架执行测试
    • 因为 JUnit 5 本质上是在测试框架内部执行这些测试
    • 包级别的可见性允许同一包内的类访问测试类,而不需要将其暴露为 public

3、@SpringBootTest工作原理

它会启动整个**Spring容器**,加载应用程序的**所有Bean**,并创建一个**完整的应用上下文**。这是集成测试,因为它模拟了应用程序的真实运行环境。

查找主配置类的两种方式:

包扫描**:默认情况下,@SpringBootTest 会从测试类所在的包开始,**向上**查找**同一包或父包**中带有** @SpringBootApplication**或**@SpringBootConfiguration**注解的类,作为应用的配置类**

显式指定**:如果 @SpringBootTest 无法自动找到 @SpringBootApplication 注解的配置类,或者你希望手动指定配置类,你可以在**@SpringBootTest 注解中使用**classes**属性显式指定应用的配置类

4、生成单元测试类

  • 在需要生成单元测试的类中按**Alt +Ins**,选择test(测试)
  • 选择测试方法
  • 生成的测试类放入与本类**相同的包结构**下

三、常用注解

1、@BeforeAll

  • 用于在**所有测试方法之前**执行的**静态**初始化代码
  • 通常用于在执行所有测试之前进行一次性设置,例如建立数据库连接、初始化共享资源等
  • 被注解的方法必须是**static**
代码语言:javascript
代码运行次数:0
运行
复制
@BeforeAll
static void setup() {
    System.out.println("Running setup before all tests...");
}

2、@AfterAll

  • 用于在**所有测试方法执行完成后**运行的**静态**清理代码
  • 通常用于释放资源、关闭连接等操作
  • 被注解的方法必须是**static**
代码语言:javascript
代码运行次数:0
运行
复制
@AfterAll
static void tearDown() {
    System.out.println("Running teardown after all tests...");
}

3、@BeforeEach

  • 用于在**每个测试方法之前**执行的初始化代码
  • 常用于在每个测试方法执行之前准备一些通用的数据或环境
代码语言:javascript
代码运行次数:0
运行
复制
@BeforeEach
void init() {
    System.out.println("Running setup before each test...");
}

4、@AfterEach

  • 用于在**每个测试方法之后**执行的清理代码
  • 常用于在每个测试方法之后恢复原状或清理一些资源
代码语言:javascript
代码运行次数:0
运行
复制
@AfterEach
void cleanup() {
    System.out.println("Running cleanup after each test...");
}

5、@DisplayName

  • 用于为测试类或测试方法提供一个更具可读性或说明性的**名称**,便于在测试报告中展示

6、@Disabled

  • 当执行**所有**测试方法时候,@Disabled注解的方法**不会执行**

7、@RepeatedTest

  • 用于多次**重复执行**某个测试,可以**指定重复次数**

四、常用断言

断言(Assertions)在单元测试中用于**验证程序行为是否符合预期**。JUnit 提供了一组用于编写断言的方法,断言的使用可以帮助判断测试是否通过。类名**org.junit.jupiter.api.Assertions**

1、assertEquals(expected, actual)

  • 验证两个对象**是否相等**
  • 可以用于**各种数据类型**,包括基本类型、对象等
代码语言:javascript
代码运行次数:0
运行
复制
assertEquals(5, 2 + 3);
assertEquals("Hello", greetingService.getGreeting());

2、assertNotEquals(expected, actual)

  • 验证两个对象**是否不相等**
代码语言:javascript
代码运行次数:0
运行
复制
assertNotEquals(10, 2 + 3);

3、assertTrue(condition)

  • 验证条件为**true**
代码语言:javascript
代码运行次数:0
运行
复制
assertTrue(5 > 3);

4、assertFalse(condition)

  • 验证条件为**false**
代码语言:javascript
代码运行次数:0
运行
复制
assertFalse(3 > 5);

5、assertNull(actual)

  • 验证对象是否为**null**
代码语言:javascript
代码运行次数:0
运行
复制
String str = null;
assertNull(str);

6、assertNotNull(actual)

  • 验证对象是否**不为null**
代码语言:javascript
代码运行次数:0
运行
复制
String str = "Hello";
assertNotNull(str);

7、assertArrayEquals(expected, actual)

  • 验证两个数组是否相等
  • 数组的**长度**和元素的**顺序**都必须相同
代码语言:javascript
代码运行次数:0
运行
复制
int[] expected = {1, 2, 3};
int[] actual = {1, 2, 3};
assertArrayEquals(expected, actual);

8、assertSame(expected, actual)

  • 验证两个对象引用是否指向**同一个对象**(即是同一个对象的引用)
代码语言:javascript
代码运行次数:0
运行
复制
Object obj = new Object();
assertSame(obj, obj);

9、assertNotSame(expected, actual)

  • 验证两个对象引用是否**不指向同一个对象**
代码语言:javascript
代码运行次数:0
运行
复制
Object obj1 = new Object();
Object obj2 = new Object();
assertNotSame(obj1, obj2);

10、fail(message)

  • 强制使测试失败
  • 通常用于标记不应该被执行的代码路径
代码语言:javascript
代码运行次数:0
运行
复制
if (someCondition) {
    fail("Unexpected condition occurred");
}

11、带有消息参数的断言

JUnit的断言方法通常有一个变体,可以带有一个额外的**字符串参数**,用于在**测试失败时提供错误消息**,帮助更快找到问题。

五、@MockBean注入

1、@MockBean的主要作用

  • @MockBean会将应用上下文中的某个Bean**替换为模拟的Bean(Mock 对象)**
  • @MockBean自动与Spring上下文集成,允许模拟的Bean被注入到需要它的其他Bean中

2、@MockBean的典型用法(模拟数据层)

假设我们有一个UserService依赖于UserRepository,而我们在测试中不想使用真实的UserRepository,而是使用**模拟对象**。

代码语言:javascript
代码运行次数:0
运行
复制
@Service
public class UserService {

    private final UserRepository userRepository;
    
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User getUserById(Long id) {
        return userRepository.findById(id);
    }
}
  • 使用**@MockBean**来模拟UserRepository
  • given**方法**模拟**了userRepository.findById(1L)** 方法的调用**,并定义了当该方法被调用时,**willReturn**表示返回一个mockUser对象**
代码语言:javascript
代码运行次数:0
运行
复制
import org.junit.jupiter.api.Test;
import org.mockito.BDDMockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.BDDMockito.given;

@SpringBootTest
public class UserServiceTest {

    @Autowired
    private UserService userService;

    // 模拟 UserRepository,替换掉应用上下文中的实际 Bean
    @MockBean
    private UserRepository userRepository;

    @Test
    void testGetUserById() {
        // 创建模拟数据
        User mockUser = new User(1L, "John Doe");

        // 使用 Mockito 的 BDD 风格方法设置模拟行为
        given(userRepository.findById(1L)).willReturn(mockUser);

        // 调用服务层方法,验证返回值是否符合预期
        User result = userService.getUserById(1L);
        assertEquals("John Doe", result.getName());
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-10-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、JUnit5介绍
    • 1、JUnit5组成结构
    • 2、什么是单元测试
  • 二、SpringBoot整合JUnit5
    • 1、快速入门
    • 2、测试类和测试方法不需要声明为public
    • 3、@SpringBootTest工作原理
    • 4、生成单元测试类
  • 三、常用注解
    • 1、@BeforeAll
    • 2、@AfterAll
    • 3、@BeforeEach
    • 4、@AfterEach
    • 5、@DisplayName
    • 6、@Disabled
    • 7、@RepeatedTest
  • 四、常用断言
    • 1、assertEquals(expected, actual)
    • 2、assertNotEquals(expected, actual)
    • 3、assertTrue(condition)
    • 4、assertFalse(condition)
    • 5、assertNull(actual)
    • 6、assertNotNull(actual)
    • 7、assertArrayEquals(expected, actual)
    • 8、assertSame(expected, actual)
    • 9、assertNotSame(expected, actual)
    • 10、fail(message)
    • 11、带有消息参数的断言
  • 五、@MockBean注入
    • 1、@MockBean的主要作用
    • 2、@MockBean的典型用法(模拟数据层)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档