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
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
- 测试类应放在
src/test/java
目录下
importorg.junit.jupiter.api.Test;importorg.springframework.boot.test.context.SpringBootTest;@SpringBootTestclassMySpringBootApplicationTests{@TestvoidcontextLoads(){// 测试 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
@BeforeAllstaticvoidsetup(){System.out.println("Running setup before all tests...");}
2、@AfterAll
- 用于在
所有测试方法执行完成后
运行的静态
清理代码 - 通常用于释放资源、关闭连接等操作
- 被注解的方法必须是
static
@AfterAllstaticvoidtearDown(){System.out.println("Running teardown after all tests...");}
3、@BeforeEach
- 用于在
每个测试方法之前
执行的初始化代码 - 常用于在每个测试方法执行之前准备一些通用的数据或环境
@BeforeEachvoidinit(){System.out.println("Running setup before each test...");}
4、@AfterEach
- 用于在
每个测试方法之后
执行的清理代码 - 常用于在每个测试方法之后恢复原状或清理一些资源
@AfterEachvoidcleanup(){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)
- 验证两个对象
是否相等
- 可以用于
各种数据类型
,包括基本类型、对象等
assertEquals(5,2+3);assertEquals("Hello", greetingService.getGreeting());
2、assertNotEquals(expected, actual)
- 验证两个对象
是否不相等
assertNotEquals(10,2+3);
3、assertTrue(condition)
- 验证条件为
true
assertTrue(5>3);
4、assertFalse(condition)
- 验证条件为
false
assertFalse(3>5);
5、assertNull(actual)
- 验证对象是否为
null
String str =null;assertNull(str);
6、assertNotNull(actual)
- 验证对象是否
不为null
String str ="Hello";assertNotNull(str);
7、assertArrayEquals(expected, actual)
- 验证两个数组是否相等
- 数组的
长度
和元素的顺序
都必须相同
int[] expected ={1,2,3};int[] actual ={1,2,3};assertArrayEquals(expected, actual);
8、assertSame(expected, actual)
- 验证两个对象引用是否指向
同一个对象
(即是同一个对象的引用)
Object obj =newObject();assertSame(obj, obj);
9、assertNotSame(expected, actual)
- 验证两个对象引用是否
不指向同一个对象
Object obj1 =newObject();Object obj2 =newObject();assertNotSame(obj1, obj2);
10、fail(message)
- 强制使测试失败
- 通常用于标记不应该被执行的代码路径
if(someCondition){fail("Unexpected condition occurred");}
11、带有消息参数的断言
**JUnit的断言方法通常有一个变体,可以带有一个额外的
字符串参数
,用于在
测试失败时提供错误消息
,帮助更快找到问题。**
五、@MockBean注入
1、@MockBean的主要作用
- @MockBean会将应用上下文中的某个Bean
替换为模拟的Bean(Mock 对象)
- @MockBean自动与Spring上下文集成,允许模拟的Bean被注入到需要它的其他Bean中
2、@MockBean的典型用法(模拟数据层)
**假设我们有一个UserService依赖于UserRepository,而我们在测试中不想使用真实的UserRepository,而是使用
模拟对象
。**
@ServicepublicclassUserService{privatefinalUserRepository userRepository;publicUserService(UserRepository userRepository){this.userRepository = userRepository;}publicUsergetUserById(Long id){return userRepository.findById(id);}}
- 使用
@MockBean
来模拟UserRepository given
方法模拟
了userRepository.findById(1L)方法的调用
,并定义了当该方法被调用时,willReturn
表示返回一个mockUser对象
importorg.junit.jupiter.api.Test;importorg.mockito.BDDMockito;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.boot.test.mock.mockito.MockBean;importstaticorg.junit.jupiter.api.Assertions.assertEquals;importstaticorg.mockito.BDDMockito.given;@SpringBootTestpublicclassUserServiceTest{@AutowiredprivateUserService userService;// 模拟 UserRepository,替换掉应用上下文中的实际 Bean@MockBeanprivateUserRepository userRepository;@TestvoidtestGetUserById(){// 创建模拟数据User mockUser =newUser(1L,"John Doe");// 使用 Mockito 的 BDD 风格方法设置模拟行为given(userRepository.findById(1L)).willReturn(mockUser);// 调用服务层方法,验证返回值是否符合预期User result = userService.getUserById(1L);assertEquals("John Doe", result.getName());}}
版权归原作者 冬天vs不冷 所有, 如有侵权,请联系我们删除。