八、测试-SpringBoot本地实战

文章目录

  • 前言
  • 一、开发阶段
    • 1. 单元测试
    • 2. 总结
  • 二、集成测试
    • 1. 热部署
  • 三、投产上线
    • 1. 打成 jar 包
      • 1. 编译构建
      • 2. 启动
    • 2. 打成 war 包
      • 1. 编译构建
      • 2. 启动
  • 四、生产运维
    • 1. 指标监控
    • 2. 应用运维
  • 五、总结


前言

SpringBoot项目测试

  在系统开发过程中,Spring Boot 项目如何测试,如何部署,在生产中有什么好的部署方案吗?

  下面简单介绍Spring Boot 如何开发、调试、打包到最后的投产上线。


一、开发阶段

1. 单元测试

  在开发阶段的时候最重要的是单元测试了, Spring Boot 对单元测试的支持已经很完善了。

  1. 依赖

在 pom 包中添加 spring-boot-starter-test 包引用

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency>
  1. 基础开发测试类

  以最简单的 helloworld 为例,在测试类的类头部需要添加:‌@RunWith(SpringRunner.class)‌和 ‌@SpringBootTest‌注解,在测试方法的顶端添加‌@Test‌即可,最后在方法上点击右键‌run‌就可以运行。

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class},webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT
)
@Slf4j
@ActiveProfiles("local")
public class BaseSpringTest {
}

注解解读

‌SpringBootTest.WebEnvironment‌是Spring Boot中的一个枚举类型,用于指定在测试或开发环境中创建的‌ApplicationContext‌的类型。它主要有以下几种模式:

‌MOCK‌:如果类路径中存在servlet API,则创建一个带有模拟servlet环境的WebApplicationContext;如果存在Spring WebFlux,则创建一个ReactiveWebApplicationContext;否则,创建一个普通的ApplicationContext。这是默认模式‌1。
‌DEFINED_PORT‌:启动一个真实的嵌入式Web服务器,并绑定到指定的端口。
‌RANDOM_PORT‌:启动一个嵌入式Web服务器,并绑定到随机端口。
‌NONE‌:不启动任何Web服务器,仅加载核心ApplicationContext。这种模式适用于不需要模拟HTTP请求或验证控制器行为的测试,如对服务层方法、DAO或其他非Web组件的测试‌2。

使用场景和选择依据

‌MOCK‌:适用于需要模拟Web环境的测试场景,例如集成测试。
‌DEFINED_PORT‌:适用于需要绑定到特定端口的测试场景。
‌RANDOM_PORT‌:适用于需要绑定到随机端口的测试场景,以避免端口冲突。
‌NONE‌:适用于不需要Web环境的测试场景,可以显著减少测试启动和执行的时间‌2。

通过合理选择WebEnvironment模式,可以优化Spring Boot应用的开发和测试过程,确保在不同环境下都能高效运行。

  1. 特别开发测试类

  实际使用中,可以按照项目的正常使用,去注入数据层代码,或者是 Service 层代码,进行测试验证, ‌spring-boot-starter-test‌提供很多基础用法,更难得的是增加了对 Controller 层测试的支持。

//简单验证结果集是否正确
Assert.assertEquals(3, userMapper.getAll().size());
//验证结果集,提示
Assert.assertTrue("错误,正确的返回值为200", status == 200); 
Assert.assertFalse("错误,正确的返回值为200", status != 200);  

引入了 ‌MockMvc‌支持了对 Controller 层的测试,简单示例如下:

public class HelloControlerTests {private MockMvc mvc;//初始化执行@Beforepublic void setUp() throws Exception {mvc = MockMvcBuilders.standaloneSetup(new HelloController()).build();}//验证controller是否正常响应并打印返回结果@Testpublic void getHello() throws Exception {mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)).andExpect(MockMvcResultMatchers.status().isOk()).andDo(MockMvcResultHandlers.print()).andReturn();}//验证controller是否正常响应并判断返回结果是否正确@Testpublic void testHello() throws Exception {mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andExpect(content().string(equalTo("Hello World")));}
}

2. 总结

  单元测试是验证代码的第一道屏障,要养成每写一部分代码就进行单元测试的习惯,不要等到全部集成后再进行测试,集成后因为更关注整体运行效果,很容易遗漏掉代码底层的bug。

二、集成测试

  整体开发完成之后进入集成测试阶段。

  Spring Boot 项目的启动入口在 Application 类中,直接运行 run 方法就可以启动项目,但是在测试的过程中需要不断的去调试代码,如果每修改一次代码就手动重启一次服务,显然很麻烦。 Spring Boot 非常贴心的给出了热部署的支持,很方便在 Web 项目中调试使用。

1. 热部署

  1. 依赖

pom 需要添加以下的配置

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional></dependency>
</dependencies>
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><fork>true</fork></configuration></plugin>
</plugins>
</build>

添加以上配置后,项目就支持了热部署,非常方便集成测试。

三、投产上线

根据部署成果物,一般分为两种:

  • 打包成 jar 包直接执行

  • 打包成 war 包放到 tomcat 服务器下。

1. 打成 jar 包

1. 编译构建

  1. 执行命令。
cd 项目根目录(和pom.xml同级)
mvn clean package
## 或者执行下面的命令
## 排除测试代码后进行打包
mvn clean package  -Dmaven.test.skip=true

打包完成后 jar 包会生成到 target 目录下,命名一般是 项目名+版本号.jar。

2. 启动

  1. 启动 jar 包命令
java -jar target/spring-boot-scheduler-1.0.0.jar

这种方式,只要控制台关闭,服务就不能访问了。

  1. 后台启动

下面我们使用在后台运行的方式来启动:

nohup java -jar target/spring-boot-scheduler-1.0.0.jar

也可以在启动的时候选择读取不同的配置文件

java -jar app.jar --spring.profiles.active=dev

也可以在启动的时候设置 jvm 参数

java -Xms10m -Xmx80m -jar app.jar

2. 打成 war 包

1. 编译构建

  1. maven 项目,修改 pom 包。将jar修改成war。
<packaging>war</packaging>  
  1. 打包时排除tomcat
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><scope>provided</scope>
</dependency>

在这里将 scope 属性设置为 provided,这样在最终形成的 WAR 中不会包含这个 JAR 包,因为 Tomcat 或 Jetty 等服务器在运行时将会提供相关的 API 类。

  1. 注册启动类

创建 ServletInitializer.java,继承 SpringBootServletInitializer ,覆盖 configure(),把启动类 Application 注册进去。外部 Web 应用服务器构建 Web Application Context 的时候,会把启动类添加进去。

public class ServletInitializer extends SpringBootServletInitializer {@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder application) {return application.sources(Application.class);}
}   
  1. 执行构建
mvn clean package  -Dmaven.test.skip=true

会在 target 目录下生成:项目名+版本号.war文件。

2. 启动

将构建好的,war包文件,拷贝到 tomcat 服务器中,启动即可。

四、生产运维

根据部署成果物,一般分为两种:

  • 打包成 jar 包直接执行

  • 打包成 war 包放到 tomcat 服务器下。

1. 指标监控

查看 JVM 参数的值,可以根据 Java 自带的 jinfo 命令

jinfo -flags pid

来查看 jar 启动后使用的是什么 gc、新生代、老年代分批的内存都是多少,示例如下:

-XX:CICompilerCount=3 -XX:InitialHeapSize=234881024 -XX:MaxHeapSize=3743416320 -XX:MaxNewSize=1247805440 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=78118912 -XX:OldSize=156762112 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseParallelGC

XX:CICompilerCount :最大的并行编译数
-XX:InitialHeapSize 和 -XX:MaxHeapSize :指定 JVM 的初始和最大堆内存大小
-XX:MaxNewSize :JVM 堆区域新生代内存的最大可分配大小
-XX:+UseParallelGC :垃圾回收使用 Parallel 收集器

2. 应用运维

  1. 如何重启?

简单粗暴,直接 kill 掉进程,再次启动 jar 包

ps -ef|grep java 
##拿到对于Java程序的pid
kill -9 pid
## 再次重启
Java -jar  xxxx.jar

当然这种方式比较传统和暴力,所以一般使用下面的方式来管理。

  1. 脚本执行,如果使用的是maven,需要包含以下的配置
<plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><executable>true</executable></configuration>
</plugin>

启动方式:

1、可以直接 ./yourapp.jar 来启动
2、注册为服务

也可以做一个软链接指向你的jar包并加入到 init.d中,然后用命令来启动。

init.d 例子:

ln -s /var/yourapp/yourapp.jar /etc/init.d/yourapp
chmod +x /etc/init.d/yourapp

这样就可以使用 stop或者是 restart命令去管理你的应用。

/etc/init.d/yourapp start|stop|restart

或者

service yourapp start|stop|restart

五、总结

后面继续介绍 Spring Boot 结合Docker 的使用,以及自动化运维 。


本文的引用仅限自我学习如有侵权,请联系作者删除。
参考知识
Spring Boot 如何优雅的进行测试打包部署


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

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

相关文章

如何在 cPanel 中创建子域名:分步指南

cPanel 是一个用于管理网站的工具&#xff0c;操作界面简单直观&#xff0c;常用于管理网站的各种功能&#xff0c;包括创建子域名。很多知名的网络服务提供商&#xff0c;如 Hostease&#xff0c;都提供了 cPanel 管理工具。 本文将详细介绍如何在 cPanel 中创建子域名&#x…

减少30%人工处理时间,AI OCR与表格识别助力医疗化验单快速处理

在医疗行业&#xff0c;化验单作为重要的诊断依据和数据来源&#xff0c;涉及大量的文字和表格信息&#xff0c;传统的手工输入和数据处理方式不仅繁琐&#xff0c;而且容易出错&#xff0c;给医院的运营效率和数据准确性带来较大挑战。随着人工智能技术的快速发展&#xff0c;…

Linux安装BellSoft JDK 17 LTS

原来使用的OpenJdk&#xff0c;看到SpringBoot官网推荐&#xff08;如下图&#xff09;贝尔实验室的JDK&#xff0c;打算换一下 官方下载链接 JKD下载 可以看到Win、Mac、Linux都提供了&#xff0c;并且还有x86架构和arm架构的 在Linux中我们可以使用 uname -a 查看当前操作系…

C++(九)

前言&#xff1a; 本文主要讲述运算符的优先顺序。 一&#xff0c;运算符的优先级。 请看以下表达式&#xff1a; a32*5 运算结果为&#xff1a;13. 可以看到&#xff0c;在此代码中&#xff0c;先运行了2*5的结果&#xff0c;在此基础上在进行3操作&#xff0c;因此结果…

学生公寓智能限电系统的功能和作用

学生公寓智能限电系统‌是一种用于管理和限制学生公寓用电的设备和技术&#xff0c;旨在确保用电安全、防止火灾事故&#xff0c;并促进节能减排。以下是关于学生公寓智能限电系统的详细介绍&#xff1a; 1、功能和作用 智能限电系统通过以下功能来管理和限制用电&#xff1a…

嵌入式入门Day25

数据结构Day 6,IO Day1 查找算法顺序查找折半查找&#xff08;二分查找&#xff09;哈希查找 IO概念标准IO创建递归索引&#xff08;用于查询结构体定义&#xff09; 文件IO标准IO缓冲区指针相关函数 查找算法 顺序查找 关键字&#xff1a;分为主关键字和次关键字主关键字&am…

内网代理转发工具

概念区分 端口转发 端口转发就是将一个端口&#xff0c;这个端口可以本机的端口也可以是本机可以访问到的任意主机的端口&#xff0c;转发到任意一台可以访问到的IP上&#xff0c;通常这个IP是公网IP。 适用端口转发的网络环境有以下几种&#xff1a; 服务器处于内网&#x…

MNIST_FC

前言 提醒&#xff1a; 文章内容为方便作者自己后日复习与查阅而进行的书写与发布&#xff0c;其中引用内容都会使用链接表明出处&#xff08;如有侵权问题&#xff0c;请及时联系&#xff09;。 其中内容多为一次书写&#xff0c;缺少检查与订正&#xff0c;如有问题或其他拓展…

掌握时间,从`datetime`开始

文章目录 掌握时间&#xff0c;从datetime开始第一部分&#xff1a;背景介绍第二部分&#xff1a;datetime库是什么&#xff1f;第三部分&#xff1a;如何安装这个库&#xff1f;第四部分&#xff1a;简单库函数使用方法1. 获取当前日期和时间2. 创建特定的日期3. 计算两个日期…

算法之括号匹配中最长有效字符串

目录 1. 题目2. 解释3. 思路4. 代码5. 总结 1. 题目 任何一个左括号都能找到和其正确配对的右括号任何一个右括号都能找到和其正确配对的左括号 求最长的有效的括号长度 2. 解释 例如&#xff0c;这里的括号 ((((()()()()()()()))()最长有效是&#xff1a;((()()()()()()(…

统信桌面专业版部署postgresql-14.2+postgis-3.2方法介绍

文章来源&#xff1a;统信桌面专业版部署postgresql-14.2postgis-3.2方法介绍 | 统信软件-知识分享平台 应用场景 CPU架构&#xff1a;X86&#xff08;海光C86-3G 3350&#xff09; OS版本信息&#xff1a;1070桌面专业版 软件信息&#xff1a;postgresql-14.2postgis-3.2 …

【书生大模型实战营】Python 基础知识-L0G2000

前言&#xff1a;本文是书生大模型实战营系列的第2篇文章&#xff0c;是入门岛的第二个任务&#xff0c;主题为&#xff1a;Python基础知识。 官方教程参考链接&#xff1a;Tutorial/docs/L0/Python at camp4 InternLM/Tutorial 1.任务概览 本关为Python基础关卡&#xff0…

智能安全新时代:大语言模型与智能体在网络安全中的革命性应用

一、引言 随着信息技术的飞速发展&#xff0c;网络安全问题日益严重&#xff0c;成为各行各业面临的重大挑战。传统的安全防护措施已难以应对日益复杂的网络威胁&#xff0c;人工智能&#xff08;AI&#xff09;技术的引入为网络安全带来了新的希望。特别是大语言模型&#xff…

数仓技术hive与oracle对比(三)

更新处理 oracle使用dblink透明网关连接其他数据库&#xff0c;mysql、sqlserver、oracle&#xff0c;然后用sql、plsql更新数据&#xff1b;或者使用etl工具实现更新。 hive使用sqoop连接mysql、sqlserver、oracle实现数据更新。 oracle oracle数据加载命令 批量sql脚本上…

在 Vue.js 中使用对象映射和枚举类型

学习啦&#xff01; 对象映射是一种将一个对象的属性名映射到另一个对象的属性名的方法。 const keyMapping {username: 用户名, gender: { label: 性别, mapping: gender }, // gender 映射为 性别email: 邮箱, // email 映射为 邮箱phone: 电话, // phone 映射为 电话addres…

嵌入式学习(15)-stm32通用GPIO模拟串口发送数据

一、概述 在项目开发中可能会遇到串口不够用的情况这时候可以用通过GPIO来模拟串口的通信方式。 二、协议格式 按照1位起始位8位数据位1位停止位的方式去编写发送端的程序。起始位拉低一个波特率的时间&#xff1b;发送8位数据&#xff1b;拉高一个波特率的时间。 三、代码 …

【C语言期末复习全攻略】:知识点汇总与考试重点剖析、附刷题资料软件

零、引用 期末考试临近&#xff0c;无论你是初学者还是“熬夜选手”&#xff0c;C语言的学习都需要系统梳理和重点突破。本文将全面总结C语言的核心知识点&#xff0c;并针对考试中常见的题型提供复习建议&#xff0c;助你轻松拿下高分。 文末提供了一款免费的C语言刷题软件 …

美颜SDK接入实战:构建智能化直播美颜APP的技术路径详解

如何将美颜SDK顺利接入并构建一个智能化的直播美颜APP呢&#xff1f;本文将从技术路径的角度&#xff0c;带你深入解析这一过程。 一、了解美颜SDK的基本功能 美颜SDK通常包括多个功能模块&#xff0c;针对不同的直播场景&#xff0c;SDK会提供针对性的优化算法&#xff0c;确…

【Spring】Spring事务和事务传播机制

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【Java】登神长阶 史诗般的Java成神之路 一、Spring事务 我们在MySQL阶段已经学习了MySQL的事务相关知识&#xff0c;详情可见 【MySQL数据库】索引与事务-CSDN博客 1、概念 我们在此做一个简单回顾…

Qt 小项目 学生管理信息系统

主要是对数据库的增删查改的操作 登录/注册界面&#xff1a; 主页面&#xff1a; 添加信息&#xff1a; 删除信息&#xff1a; 删除第一行&#xff08;支持多行删除&#xff09; 需求分析&#xff1a; 用QT实现一个学生管理信息系统&#xff0c;数据库为MySQL 要求&#xf…