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-springboot
  jackson:
    time-zone: Asia/Shanghai
    date-format: yyyy-MM-dd HH:mm:ss
    default-property-inclusion: non_null
server:
  port: 8888
  servlet:
    context-path: /api
logging:
  level:
    root: error
    com.coderlk: debug
app:
  config:
    upload-addr: /opt/upload
    app-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;

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @Bean
    @ConfigurationProperties(prefix = "app.config")
    public AppConfigProperties appConfigProperties() {
        return new AppConfigProperties();
    }

    @Bean
    public AppConfigProperties appConfigPropertiesNon() {
        return new AppConfigProperties();
    }

    @Bean
    public 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 进行测试的一些关键点:

依赖管理

  1. 确保项目中包含相关依赖
  • 默认情况下,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>

编写测试

  1. 配置JUnit 5
  • Spring Boot 3 默认启用了 JUnit 5,因此只需按照 JUnit 5 的方式编写测试代码即可。你可以直接使用 @SpringBootTest 注解来加载 Spring Boot 应用程序上下文进行集成测试。

  1. 编写测试类
  • 创建一个简单的 JUnit 5 测试类,并使用 @SpringBootTest 加载整个应用上下文。
  • 使用 @Test@BeforeEach@AfterEach 等注解定义测试方法及其生命周期行为。


import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class MyApplicationTests {

    @Test
    void test() {
        // 这里写测试逻辑
    }
}

JUnit 5 新特性

  1. 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 {

    @BeforeAll
    static void initAll() { /* 初始化 */ }

    @BeforeEach
    void init() { /* 每个测试前执行 */ }

    @DisplayName("成功的测试")
    @Test
    void succeedingTest() { /* 测试逻辑 */ }

    @Test
    void failingTest() {
        fail("一个失败的测试");
    }

    @Test
    @Disabled("为了演示目的禁用")
    void skippedTest() { /* 不会被执行 */ }

    @Test
    void abortedTest() {
        assumeTrue("abc".contains("Z"));
        fail("测试应该被终止");
    }

    @AfterEach
    void tearDown() { /* 每个测试后执行 */ }

    @AfterAll
    static void tearDownAll() { /* 清理工作 */ }

    @Nested
    @DisplayName("当栈是新的时候")
    class WhenNew {

        Stack<Object> stack;

        @BeforeEach
        void 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 {

    @Test
    void 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是面向全球开发者的开源社区,包括原创博客,开源代码托管,代码协作,项目管理等。与开发者社区互动,提升您的研发效率和质量。icon-default.png?t=O83Ahttps://gitcode.com/fokman/springboot-demo.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/938535.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

fabric.js

目录 一、在canvas上画简单的图形 二、在canvas上用路径(Path)画不规则图形 三、在canvas上插入图片并设置旋转属性(angle) 四、让元素动起来(animate) 五、图像过滤器(filters)让图片多姿多彩 六、颜色模式(Color)和相互转换(toRgb、toHex) 七、对图形的渐变填充(Gradi…

ActiveMQ 反序列化漏洞CVE-2015-5254复现

文章目录 一、产生原因二、利用条件三、利用过程四、PoC&#xff08;概念验证&#xff09;五、poc环境验证使用find搜索vulhub已安装目录打开activeMQ组件查看配置文件端口启动镜像-文件配置好后对于Docker 镜像下载问题及解决办法设置好镜像源地址&#xff0c;进行重启docker查…

给新ubuntu电脑配置远程控制环境和c++版本的opencv环境

目录 改用户密码安装ssh sever安装net-tools配置vscode安装vim配置C opencv1. 安装g, cmake, make2.安装opencv依赖库3.下载opencv源文件&#xff08;1&#xff09;方法一&#xff1a;官网下载&#xff08;2&#xff09;方法二&#xff1a;GitHub下载方式&#xff1a; 4. Cmake…

如何在 Debian 12 上安装和使用 Vuls 漏洞扫描器

简介 Vuls 是一款无代理、免费且开源的 Linux 和 FreeBSD 漏洞扫描器。Vuls 主要用 Go 语言编写&#xff0c;可以在任何地方运行。你可以在云端、本地和 Docker 上运行 Vuls&#xff0c;并且它支持主要的发行版。Vuls 提供高质量的扫描&#xff0c;支持多个漏洞数据库&#xf…

Python-装饰器(Decorator)详解

在python中&#xff0c;函数是一等公民&#xff0c;意味着函数可以像其他对象一样被赋值、传递参数、作为返回值等。装饰器的基本语法是使用符号将一个函数作为参数传递给另一个函数&#xff08;即装饰器&#xff09;。被装饰的函数在被调用时&#xff0c;实际上会执行装饰器函…

数据结构_拓扑排序

拓扑排序 &#xff08;所有点按照先后顺序排序&#xff09; 1.先找到入度为0的点&#xff0c;记录之后&#xff0c;删除这个点和它的出边&#xff1b; 2.若有两个可选&#xff0c;随便选择一个 例 a的入度为0,选a [a] 随便选一个 [a,e] 再找入度为0的点 再选c 最后选d 拓…

MinerU:PDF文档提取工具

目录 docker一键启动本地配置下载模型权重文件demo.py使用命令行启动GPU使用情况 wget https://github.com/opendatalab/MinerU/raw/master/Dockerfile docker build -t mineru:latest .docker一键启动 有点问题&#xff0c;晚点更新 本地配置 就是在Python环境中配置依赖和…

redis集群安装部署 redis三主三从集群

redis集群安装部署 redis三主三从集群 1、下载redis2、安装redis集群 三主三从3、配置redis开机自启动3.1、建立启动脚本3.2、复制多份redis启动脚本给集群使用3.3、添加可执行权限3.4、配置开机自启动 1、下载redis 本次redis安装部署选择当前最新的稳定版本7.4.1 下载链接: …

Fiddler简单使用

Fiddler使用方法 1.作用 接口测试&#xff0c;发送自定义请求&#xff0c;模拟小型的接口测试定位前后端bug&#xff0c;抓取协议包&#xff0c;前后端联调构建模拟测试场景&#xff0c;数据篡改&#xff0c;重定向弱网测试&#xff0c;模拟限速操作&#xff0c;弱网&#xf…

203.PyQt5_QTreeWidget_项处理_树形结构

课 程 推 荐我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)教程合集 👈👈…

6.2 MapReduce工作原理

MapReduce工作原理涉及将大数据集分割成小块并行处理。Map任务读取数据块并输出中间键值对&#xff0c;而Reduce任务则处理这些排序后的数据以生成最终结果。MapTask工作包括读取数据、应用Map函数、收集输出、内存溢出时写入磁盘以及可选的Combiner局部聚合。ReduceTask工作则…

【线性代数】理解矩阵乘法的意义(点乘)

刚接触线性代数时&#xff0c;很不理解矩阵乘法的计算规则&#xff0c;为什么规则定义的看起来那么有规律却又莫名其妙&#xff0c;现在参考了一些资料&#xff0c;回过头重新总结下个人对矩阵乘法的理解&#xff08;严格来说是点乘&#xff09;。 理解矩阵和矩阵的乘法&#x…

Win11安装安卓子系统WSA

文章目录 简介一、启用Hyper-V二、安装WSA三、安装APKAPK商店参考文献 简介 WSA&#xff1a;Windows Subsystem For Android 一、启用Hyper-V 控制面板 → 程序和功能 → 启用或关闭 Windows 功能 → 勾选 Hyper-V 二、安装WSA 进入 Microsoft Store&#xff0c;下拉框改为 …

Tree-of-Counterfactual Prompting for Zero-Shot Stance Detection

论文地址&#xff1a;Tree-of-Counterfactual Prompting for Zero-Shot Stance Detection - ACL Anthologyhttps://aclanthology.org/2024.acl-long.49/ 1. 概述 立场检测被定义为对文本中立场态度的自动推断。根据 Biber 和 Finegan (1988) 的定义&#xff0c;立场包含两个主…

轻松上手:使用 Vercel 部署 HTML 页面教程

&#x1f600; 在学习前端的过程中&#xff0c;部署项目往往是一个令人头疼的问题。然而&#xff0c;Vercel 为我们提供了一个便捷且免费的解决方案。 Vercel 是一个强大的云平台&#xff0c;专门用于前端项目的部署和托管。它不仅支持多种前端框架和静态网站生成器&#xff0…

QT从入门到精通(二) ——信号与槽机制

Qt 的信号与槽机制&#xff08;Signal and Slot&#xff09;是 Qt 框架 中用于对象间通信的核心机制之一。它允许对象之间进行松耦合的事件驱动式通信&#xff0c;尤其适合 GUI 应用程序 中的事件处理。 1. 基本概念 信号 (Signal) 当对象的状态发生变化时&#xff0c;它会发…

数据结构:Win32 API详解

目录 一.Win32 API的介绍 二.控制台程序(Console)与COORD 1..控制台程序(Console): 2.控制台窗口坐标COORD&#xff1a; 3.GetStdHandle函数&#xff1a; &#xff08;1&#xff09;语法&#xff1a; &#xff08;2&#xff09;参数&#xff1a; 4.GetConsoleCursorInf…

kubeadm_k8s_v1.31高可用部署教程

kubeadm_k8s_v1.31高可用部署教程 实验环境部署拓扑图**部署署架构****Load Balance****Control plane node****Worker node****资源分配&#xff08;8台虚拟机&#xff09;**集群列表 前置准备关闭swap开启ipv4转发更多设置 1、Verify the MAC address and product_uuid are u…

鸿蒙元服务项目实战:备忘录UI页面开发

前言 之前写过一篇关于元服务项目的上架流程&#xff0c;为了更好的了解及开发元服务&#xff0c;准备从0到1简单开发一个小项目&#xff0c;也希望能够帮助到刚刚介入到鸿蒙开发的同学&#xff0c;具体项目呢&#xff0c;也是十分的简单&#xff0c;就是一个小巧的备忘录项目&…

Linux-ubuntu点LED灯C语言版

​ 一&#xff0c;C语言点灯 1.寄存器配置 设置为SVC模式&#xff0c;复用寄存器设置GPIO1-IO003,设置电气属性&#xff0c;设置为输出模式。 2.软件 汇编语言对模式设置&#xff0c;并且将堆栈指针指向主程序&#xff1a; .global _start_start: /*设置为svr模式 */mrs …