Springboot3.x配置类(Configuration)和单元测试

news2024/12/18 22:47:47

配置类在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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot增删改查导入导出操作【模板】

SpringBoot增删改查导入导出操作【模板】 文章目录 SpringBoot增删改查导入导出操作【模板】前期数据库操作IDEA上进行操作1. 创建 Spring Boot 项目2. 项目结构3. pom.xml文件4. 配置数据库连接并进行测试5. 创建实体类6. 创建 MyBatis Mapper7. 创建服务层8. 创建控制器9. 启…

mfc140.dll是什么东西?mfc140.dll缺失的几种具体解决方法

mfc140.dll是Microsoft Foundation Classes&#xff08;MFC&#xff09;库中的一个动态链接库&#xff08;DLL&#xff09;文件&#xff0c;它是微软基础类库的一部分&#xff0c;为Windows应用程序的开发提供了丰富的类库和接口。MFC库旨在简化Windows应用程序的开发过程&…

探索Starship:一款用Rust打造的高性能终端

在终端的世界里&#xff0c;效率和美观往往并行不悖。今天&#xff0c;我们要介绍的是一款名为Starship的终端工具&#xff0c;它以其轻量级、高颜值和强大的自定义功能&#xff0c;赢得了众多开发者的青睐。 安装 任选一种方式进行安装 Windows &#x1fa9f; # scoop scoo…

2024年NSSCTF秋季招新赛-WEB

The Beginning F12看源码&#xff0c;有flag http标头 黑吗喽 题目说要在发售时的0点0分&#xff0c;所以添加标头data Date: Tue, 20 Aug 2024 00:00:00 GMT然后改浏览器头 User-Agent: BlackMonkey曲奇就是Cookie cookieBlackMonkey这个一般就是Referer Referer:wukon…

TQ15EG开发板教程:使用SSH登录petalinux

本例程在上一章“创建运行petalinux2019.1”基础上进行&#xff0c;本例程将实现使用SSH登录petalinux。 将上一章生成的BOOT.BIN与imag.ub文件放入到SD卡中启动。给开发板插入电源与串口&#xff0c;注意串口插入后会识别出两个串口号&#xff0c;都需要打开&#xff0c;查看串…

windos系统安装-mysql 5.7 zip压缩包教程

一, 安装包下载 在mysql官网上下载mysql5.7版本的压缩包 官方网址: https://dev.mysql.com/downloads/mysql/5.7.html#downloads选择历史版本 选择系统和数据库版本下载 下载完成后解压到安装的目录 二, 新增数据目录,配置文件, 配置环境变量 新建data文件夹用于存放数据库…

js 获取屏幕高度和宽度的几种方式

1、document.documentElement.clientHeight 屏幕可视区域高度&#xff0c;文档的根元素&#xff08;通常是 <html> 元素&#xff09;的高度&#xff0c;但会受到CSS样式的影响。 实际应用&#xff1a;对于H5的移动端&#xff0c;希望video元素在全屏状态下占满整个手机屏…

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;立场包含两个主…

css基础-认识css

什么是css css是一个样式表&#xff0c;是对html的一种装饰&#xff0c;它决定了浏览器如何显示html元素&#xff0c;例如&#xff1a; h1 {color:blue; //文字颜色是蓝色font-size:12px; //字体大小为12像素 }上段css代码就是对HTML 中 <h1>标签的修饰&#xff1b;所以…

【Unity功能集】TextureShop纹理工坊(二)图层(下)

项目源码&#xff1a;后期发布 索引 图层渲染绘画区域图层Shader 编辑器编辑模式新建图层设置当前图层上、下移动图层删除图层图层快照 图层 在PS中&#xff0c;图层的概念贯穿始终&#xff08;了解PS图层&#xff09;&#xff0c;他可以称作PS最基础也是最强大的特性之一。 …

云计算HCIP-OpenStack02

书接上回&#xff1a; 云计算HCIP-OpenStack01-CSDN博客 7.OpenStack核心服务 7.1Horizon&#xff1a;界面管理服务 Horizon提供了OpenStack中基于web界面的管理控制页面&#xff0c;用户或者是管理员都需要通过该服务进行OpenStack的访问和控制 界面管理服务需要依赖于keyston…

Word2Vec:将词汇转化为向量的技术

文章目录 Word2Vec来龙去脉分层Softmax负采样 Word2Vec 下面的文章纯属笔记&#xff0c;看完后不会有任何收获&#xff0c;如果想理解这两种优化技术&#xff0c;给大家推荐一篇博客&#xff0c;讲的很好&#xff1a; 详解-----分层Softmax与负采样 来龙去脉 word2vec,即将词…

电商商品详情API接口(item get)数据分析上货

电商商品详情API接口&#xff08;item get&#xff09;在数据分析与商品上货方面发挥着重要作用。以下是对这两个方面的详细探讨&#xff1a; 一、数据分析 数据源获取&#xff1a; 商品详情API接口提供了丰富的数据源&#xff0c;包括商品的标题、价格、库存、描述、图片、用…

如何将你的 Ruby 应用程序从 OpenSearch 迁移到 Elasticsearch

作者&#xff1a;来自 Elastic Fernando Briano 将 Ruby 代码库从 OpenSearch 客户端迁移到 Elasticsearch 客户端的指南。 OpenSearch Ruby 客户端是从 7.x 版 Elasticsearch Ruby 客户端分叉而来的&#xff0c;因此代码库相对相似。这意味着当将 Ruby 代码库从 OpenSearch 迁…

如何对 Java 项目简化接口设计提升开发效率

文章目录 摘要引言简洁接口设计的原则示例代码OrderProcessor 接口StandardOrderProcessor 实现类Order 数据类调用方代码&#xff1a;OrderService 模块之间的协作QA 环节总结参考资料 摘要 简洁的接口设计可以有效降低代码依赖与耦合度&#xff0c;提高代码的可维护性和扩展…

Python字符串及正则表达式(十):字符串常用操作、字符串编码转换

前言&#xff1a;在编程的世界里&#xff0c;字符串无处不在。它们是构建用户界面、存储数据、进行通信的基础元素。无论是财务系统的总账报表、电子游戏的比赛结果&#xff0c;还是火车站的列车时刻表&#xff0c;这些信息最终都需要以文本的形式呈现给用户。这些文本的背后&a…

JAVA爬虫获取1688关键词接口

以下是使用Java爬虫获取1688关键词接口的详细步骤和示例代码&#xff1a; 一、获取API接口访问权限 要使用1688关键词接口&#xff0c;首先需要获取API的使用权限&#xff0c;并了解接口规范。以下是获取API接口的详细步骤&#xff1a; 注册账号&#xff1a;在1688平台注册一…

【AIGC】与模型对话:理解与预防ChatGPT中的常见误解

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;模型的工作原理和用户期望差异人工智能模型的基本工作原理认知上的局限与误解用户期望与模型实际能力的差距精确理解用户意图的重要性实际应用中的建议 &…

UE5制作倒计时功能

设置画布和文本 文本绑定 格式化时间 转到事件图表&#xff0c;计算时间&#xff0c;时间结束后面的事件可以按自己需求写 进入关卡蓝图&#xff0c;添加倒计时UI

Excel + Notepad + CMD 命令行批量修改文件名

注意&#xff1a;该方式为直接修改原文件的文件名&#xff0c;不会生成新文件 新建Excel文件 A列&#xff1a;固定为 renB列&#xff1a;原文件名称C列&#xff1a;修改后保存的名称B列、C列&#xff0c;需要带文件后缀&#xff0c;为txt文件就是.txt结尾&#xff0c;为png图片…