Springboot3.x配置类(Configuration)和单元测试
配置类在Spring Boot框架中扮演着关键角色,它使开发者能够利用Java代码定义Bean、设定属性及调整其他Spring相关设置,取代了早期版本中依赖的XML配置文件。
- 集中化管理:借助
@Configuration注解,Spring Boot让用户能在一个或几个配置类中统一管理所有配置信息。这种方式不仅简化了Bean的定义和配置,还提高了配置管理和维护的效率,避免了分散在多个XML文件中的复杂性。 - 类型安全配置:由于配置工作是在Java代码内完成,因此可以充分利用Java编译时的类型检查机制,确保配置的准确性。这种做法有效防止了因拼写错误或配置不当引起的运行时错误,增强了应用程序的稳定性和可靠性。
- 条件化配置能力:该框架还提供了基于条件的配置选项,允许根据特定条件(例如环境变量、系统属性等)动态决定是否创建或配置某个Bean。这项特性增加了应用部署的灵活性,使其更易于适应不同的运行环境和需求变化。
- 自动装配(Autowiring)支持:Spring Boot内置的自动装配功能可以根据Bean的类型、名称或是限定符自动注入所需的依赖项。这大大减少了手动配置依赖关系的工作量,同时也降低了配置出错的风险。
示例代码
首先定义一个yml的配置文件
spring:application:name: demo-springbootjackson:time-zone: Asia/Shanghaidate-format: yyyy-MM-dd HH:mm:ssdefault-property-inclusion: non_null
server:port: 8888servlet:context-path: /api
logging:level:root: errorcom.coderlk: debug
app:config:upload-addr: /opt/uploadapp-key: 12345678
解析配置文件
下面的这个Bean映射到application.yml 中的app:config:xxx的配置
package com.coderlk.interceptor.demo.config;import lombok.Data;@Data
public class AppConfigProperties {private String uploadAddr;private String appKey;
}
UploadTools.java
package com.coderlk.interceptor.demo.config;import lombok.Data;
import lombok.extern.slf4j.Slf4j;@Data
@Slf4j
public class UploadTools {private AppConfigProperties appConfigProperties;public void upload() {log.info("app.config:{}", appConfigProperties);}
}
AppConfiguration.java
package com.coderlk.interceptor.demo.config;import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;@Configuration
public class AppConfiguration {@Value("${spring.application.name}")public String appName;@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}@Bean@ConfigurationProperties(prefix = "app.config")public AppConfigProperties appConfigProperties() {return new AppConfigProperties();}@Beanpublic AppConfigProperties appConfigPropertiesNon() {return new AppConfigProperties();}@Beanpublic UploadTools uploadTools(@Qualifier("appConfigProperties") AppConfigProperties properties) {UploadTools uploadTools = new UploadTools();uploadTools.setAppConfigProperties(properties);return uploadTools;}
}
关键点解析
- @Configuration:标记该类是一个配置类,其中的方法可以用
@Bean注解来定义Spring容器管理的bean。 - **@Value("...")∗∗:用于将配置文件(如‘application.yml‘或‘application.properties‘)中的值注入到字段、构造函数参数或方法参数中。这里的‘...")∗∗:用于将配置文件(如‘application.yml‘或‘application.properties‘)中的值注入到字段、构造函数参数或方法参数中。这里的‘{spring.application.name}`是Spring Boot默认提供的属性之一,代表应用的名字。
- @Bean:用来声明一个方法,其返回的对象应该被注册为Spring容器中的一个bean。每个
@Bean方法实际上就是一种创建bean的方式。 - @ConfigurationProperties(prefix = "app.config"):允许你将一组特定前缀的配置属性映射到一个Java对象上。这简化了从配置文件读取多个相关属性的过程。在这个例子中,所有以
app.config开头的属性都会映射到AppConfigProperties对象中。 - AppConfigProperties 和 UploadTools:是我们自定义的组件类,
AppConfigProperties可能用于保存应用程序的配置属性,而UploadTools则可能是负责处理上传逻辑的组件,它依赖于AppConfigProperties来进行某些操作。
测试
请求体
GET http://localhost:8888/api/uploader
Token: 213coiu423m
控制台打印结果
INFO 13428 --- [interceptor-demo] [nio-8888-exec-5] c.c.interceptor.demo.config.UploadTools : app.config:AppConfigProperties(uploadAddr=/opt/upload, appKey=12345678)
单元测试
Spring Boot 3 与 JUnit 5 的集成使得开发者可以方便地为他们的应用程序编写和运行单元测试及集成测试。以下是有关如何在 Spring Boot 3 中使用 JUnit 5 进行测试的一些关键点:
依赖管理
- 确保项目中包含相关依赖:
- 默认情况下,
spring-boot-starter-test依赖项已经包含了 JUnit 5 的支持,因此你通常不需要显式添加 JUnit 5 的依赖。 - 如果你需要特定版本的 JUnit 5 或者有其他特殊需求,则可以在
pom.xml(对于 Maven 项目)或build.gradle(对于 Gradle 项目)中添加相应的依赖。
<dependencies><!-- Spring Boot Starter Test(包含JUnit 5支持) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies>
编写测试
- 配置JUnit 5:
- Spring Boot 3 默认启用了 JUnit 5,因此只需按照 JUnit 5 的方式编写测试代码即可。你可以直接使用
@SpringBootTest注解来加载 Spring Boot 应用程序上下文进行集成测试。
- 编写测试类:
- 创建一个简单的 JUnit 5 测试类,并使用
@SpringBootTest加载整个应用上下文。 - 使用
@Test、@BeforeEach、@AfterEach等注解定义测试方法及其生命周期行为。
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
class MyApplicationTests {@Testvoid test() {// 这里写测试逻辑}
}
JUnit 5 新特性
- JUnit 5 新增特性:
- 注解:提供了如
@ParameterizedTest、@RepeatedTest、@DisplayName等新注解。 - 断言:JUnit 5 提供了更加强大的内置断言库,比如
Assertions.assertThat()和假设条件Assumptions.assumeThat()。 - 嵌套测试:通过
@Nested注解实现更加结构化的测试组织,允许创建内部类来进行分组测试。 - 扩展模型:可以通过
@ExtendWith注解引入自定义扩展,从而增强测试功能。
例如,下面是一个使用了多个新特性的测试例子:
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.*;import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Timeout;
import org.junit.jupiter.api.extension.ExtendWith;class StandardTests {@BeforeAllstatic void initAll() { /* 初始化 */ }@BeforeEachvoid init() { /* 每个测试前执行 */ }@DisplayName("成功的测试")@Testvoid succeedingTest() { /* 测试逻辑 */ }@Testvoid failingTest() {fail("一个失败的测试");}@Test@Disabled("为了演示目的禁用")void skippedTest() { /* 不会被执行 */ }@Testvoid abortedTest() {assumeTrue("abc".contains("Z"));fail("测试应该被终止");}@AfterEachvoid tearDown() { /* 每个测试后执行 */ }@AfterAllstatic void tearDownAll() { /* 清理工作 */ }@Nested@DisplayName("当栈是新的时候")class WhenNew {Stack<Object> stack;@BeforeEachvoid createNewStack() {stack = new Stack<>();}@Test@DisplayName("是空的")void isEmpty() {assertTrue(stack.isEmpty());}@Test@DisplayName("抛出异常时弹出")void throwsExceptionWhenPopped() {assertThrows(EmptyStackException.class, stack::pop);}}
}
综上所述,在 Spring Boot 3 中使用 JUnit 5 可以让你充分利用现代 Java 测试框架的优点,同时保持与 Spring 生态系统的紧密集成。这不仅简化了测试设置过程,还提高了测试代码的质量和可读性。
断言
JUnit 5 提供了一个丰富的断言库,允许开发者编写清晰、表达力强的测试用例。相比之前的版本,JUnit 5 的断言功能更为强大和灵活,支持多种类型的断言以适应不同的测试场景。以下是一些常用的 JUnit 5 断言方法及其使用示例:
基本断言
assertEquals(expected, actual):验证两个值是否相等。
assertTrue(condition) 和 assertFalse(condition):检查条件是否为真或假。
assertNull(object) 和 assertNotNull(object):检查对象是否为 null 或不为 null。
package com.coderlk.interceptor.demo;import org.junit.jupiter.api.Test;import static org.junit.jupiter.api.Assertions.*;public class UnitDemoTest {@Testvoid basicAssertions() {assertEquals(2 + 2, 4, "简单的加法");assertTrue("foo".startsWith("f"), "字符串开始于 'f'");assertNull(null, "值应该是null");}
}
集合和数组断言
@Test
void collectionAssertions() {String[] expected = {"a", "b", "c"};String[] actual = {"a", "b", "c"};assertArrayEquals(expected, actual, "数组应该相等");List<String> expectedList = Arrays.asList("apple", "banana", "orange");List<String> actualList = Arrays.asList("apple", "banana", "orange");assertIterableEquals(expectedList, actualList, "列表应该相等");
}
异常处理断言
- assertThrows(exceptionClass, executable):用于验证代码块是否抛出了预期的异常。
@Test
void exceptionAssertions() {Exception exception = assertThrows(IllegalArgumentException.class, () -> {throw new IllegalArgumentException("一个非法参数异常");});assertEquals("一个非法参数异常", exception.getMessage());
}
超时断言
- assertTimeout(timeout, executable):确保一段代码在指定时间内完成执行。
- assertTimeoutPreemptively(Duration timeout, Executable executable):强制性地限制一段代码的执行时间,并在超时时立即终止执行。
@Test
void timeoutAssertions() {// 如果这段代码超过1秒,测试将失败assertTimeout(Duration.ofSeconds(1), () -> {// 执行一些操作...});// 使用 preemptive 超时策略,如果超时则立即中断执行assertTimeoutPreemptively(Duration.ofMillis(100), () -> {Thread.sleep(200); // 这个应该会导致超时异常});
}
组合断言
- assertAll(Executable... executables):可以将多个断言组合在一起,在所有断言都通过的情况下才认为整个断言成功。如果任何一个断言失败,则整个测试失败。
@Test
void multipleAssertions() {assertAll(() -> assertEquals(2, 2),() -> assertTrue("hello".startsWith("he")),() -> assertFalse("test".isEmpty()));
}
条件断言
- assumeTrue(boolean condition) 和 assumeFalse(boolean condition):假设条件成立或不成立,如果不满足假设条件,则跳过该测试。
@Test
void conditionalAssertions() {assumeTrue("abc".contains("a"));// 如果假设条件不满足,后面的代码不会被执行System.out.println("假设条件满足");
}
这些只是 JUnit 5 断言库的一部分功能。JUnit 5 的断言机制非常强大且灵活,能够帮助开发者更有效地进行单元测试和集成测试,确保应用程序的质量和可靠性。如果你需要更加复杂的断言逻辑,还可以考虑使用第三方库如 AssertJ 或 Hamcrest,它们提供了更加丰富的断言功能。
本课程学习代码,同步更新到
https://gitcode.com/fokman/springboot-demo.gitGitCode是面向全球开发者的开源社区,包括原创博客,开源代码托管,代码协作,项目管理等。与开发者社区互动,提升您的研发效率和质量。
https://gitcode.com/fokman/springboot-demo.git
相关文章:
Springboot3.x配置类(Configuration)和单元测试
配置类在Spring Boot框架中扮演着关键角色,它使开发者能够利用Java代码定义Bean、设定属性及调整其他Spring相关设置,取代了早期版本中依赖的XML配置文件。 集中化管理:借助Configuration注解,Spring Boot让用户能在一个或几个配…...
java后端环境配置
因为现在升学了,以前本来想毕业干java的,很多java的环境配置早就忘掉了(比如mysql maven jdk idea),想写个博客记录下来,以后方便自己快速搭建环境 JAVA后端开发配置 环境配置jdkideamavenMySQLnavicate17…...
手眼标定工具操作文档
1.手眼标定原理介绍 术语介绍 手眼标定:为了获取相机与机器人坐标系之间得位姿转换关系,需要对相机和机器人坐标系进行标定,该标定过程成为手眼标定,用于存储这一组转换关系的文件称为手眼标定文件。 ETH:即Eye To …...
WebGIS城市停水及影响范围可视化实践
目录 前言 一、相关信息介绍 1、停水信息的来源 2、停水包含的相关信息 二、功能简介 1、基础小区的整理 2、停水计划的管理 三、WebGIS空间可视化 1、使用到的组件 2、停水计划的展示 3、影响小区的展示 4、实际效果 四、总结 前言 城市停水,一个看似…...
无管理员权限 LCU auth-token、port 获取(全网首发 go)
一: 提要: 参考项目: https://github.com/Zzaphkiel/Seraphine 想做一个 lol 查战绩的软件,并且满足自己的需求(把混子和大爹都表示出来),做的第一步就是获取 lcu token ,网上清一色…...
【数字花园】数字花园(个人网站、博客)搭建经历教程
目录 写在最最前面数字花园的定义第一章:netlify免费搭建数字花园相关教程使用的平台步骤信息管理 第二章:本地部署数字花园数字花园网站本地手动部署方案1. 获取网站源码2.2 安装 Node.js 3. 项目部署3.1 安装项目依赖3.2 构建项目3.3 启动http服务器 4…...
python模拟练习第一期
问题一 如果一个数 p 是个质数,同时又是整数 a的约数,则 p 称为 a的一个质因数。 请问 2024 有多少个质因数? 步骤 1: 分解 2024 首先,2024 是偶数,说明可以被 2 整除。我们从 2 开始进行除法分解: 202…...
Xcode
info.plist Appearance Light 关闭黑暗模式 Bundle display name 设置app名称,默认为工程名 Location When In Use Usage Description 定位权限一共有3个key 1.Privacy - Location When In Use Usage Description 2.Privacy - Location Always and When In U…...
RabbitMQ安装延迟消息插件(mq报错)
之前启动一个springboot的单体项目,一直mq的错误,即便我更新了最新版本的mq,还是报错。 后来才发现,项目使用了延时队列,是需要单独下载延时插件的。 1如果判断mq有没有延时队列插件【没有x-delayed-message】 2下载…...
es 3期 第15节-词项查询与跨度查询实战运用
#### 1.Elasticsearch是数据库,不是普通的Java应用程序,传统数据库需要的硬件资源同样需要,提升性能最有效的就是升级硬件。 #### 2.Elasticsearch是文档型数据库,不是关系型数据库,不具备严格的ACID事务特性ÿ…...
iOS Delegate模式
文章目录 一、 Delegate 模式的概念二、Delegate 的实现步骤步骤 1: 定义一个协议(Protocol)步骤 2: 在主类中添加一个 delegate 属性步骤 3: 实现协议的类遵守协议并实现方法步骤 4: 设置 delegate 三、Delegate 模式的特点四、Delegate 模式的常见场景…...
java-使用druid sqlparser将SQL DDL脚本转化为自定义的java对象
java-使用druid sqlparser将SQL DDL脚本转化为自定义的java对象 一、引言二、环境三、待解析的DDL四、解析后的对象结构五、完整的UT类六、控制台输出总结 一、引言 在日常开发中,有些需要对SQL进行解析的场景,比如读取表结构信息,生成文档、…...
React状态管理常见面试题目(一)
1. Redux 如何实现多个组件之间的通信?多个组件使用相同状态时如何进行管理? Redux 实现组件通信 Redux 是一个集中式的状态管理工具,通过共享一个全局 store 来实现多个组件之间的通信。 通信机制: 所有状态保存在 Redux 的全局 store 中。使用 ma…...
jenkins 出现 Jenkins: 403 No valid crumb was included in the request
文章目录 前言解决方式:1.跨站请求为找保护勾选"代理兼容"2.全局变量或者节点上添加环境变量3.(可选)下载插件 the strict Crumb Issuer plugin4.重启 前言 jenkins运行时间长了,经常出现点了好几次才能构建,然后报了Je…...
【前端面试】list转树、拍平, 指标,
这个题目涉及的是将一组具有父子关系的扁平数据转换为树形结构,通常称为“树形结构的构建”问题。类似的题目包括: 1. 组织架构转换 给定一个公司的员工列表,每个员工有 id 和 managerId,其中 managerId 表示该员工的上级。任务…...
游戏引擎学习第43天
仓库 https://gitee.com/mrxiao_com/2d_game 介绍运动方程 今天我们将更进一步,探索运动方程,了解真实世界中的物理,并调整它们,以创建一种让玩家感觉愉悦的控制体验。这并不是在做一个完美的物理模拟,而是找到最有趣…...
NVM:安装配置使用(详细教程)
文章目录 一、简介二、安装 nvm三、配置 nvm 镜像四、配置环境变量五、使用教程5.1 常用命令5.2 具体案例 六、结语 一、简介 在实际的开发和学习中可能会遇到不同项目的 node 版本不同,而出现的兼容性问题。 而 nvm 就可以很好的解决这个问题,它可以在…...
matlab测试ADC动态性能的原理
目录 摘要: 简介: 动态规范和定义 动态规格: 双面到单边的功率谱转换 摘要: 模数转换器(adc)代表了接收器、测试设备和其他电子设备中的模拟世界和数字世界之间的联系。正如本文系列的第1部分中所概述…...
PostgreSQL JSON/JSONB 查询与操作指南
PostgreSQL 提供了强大的 JSON 和 JSONB 数据类型及相关操作,适用于存储和查询半结构化数据。本文将详细介绍其常用操作。 1. 基础操作 1.1 JSON 属性访问 ->: 返回 JSON 对象中的值,结果为 JSON 格式。 SELECT {"a": {"b": 1…...
【Isaac Lab】Ubuntu22.04安装英伟达驱动
目录 1.1 禁用nouveau驱动 1.2 安装必要的依赖项 1.3 下载安装 1.4 查看是否安装成功 1.5 安装CUDA 1.5.1 下载 1.5.2 按照提示进行下载安装 1.5.3 添加环境变量 1.5.4 测试CUDA是否安装成功 1.1 禁用nouveau驱动 输入以下命令打开blacklist.conf文件 sudo vim /etc…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...
力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
