当前位置: 首页 > news >正文

Spring Boot单元测试

什么是单元测试?

单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证的过程就叫单元测试。

单元测试是开发人员编写的一小段代码,用于检验被测代码的一个很小的、很明确的(代码) 功能是否正确。执行单元测试就是为了证明某段代码的执行结果是否符合我们的预期。如果测试结果符合我们的预期,称之为测试通过,否则就是测试未通过(或者叫测试失败)

Java 中的最小测试单元就到方法了,也就说对方法的测试就是单元测试

单元测试的作用

在没有接触单元测试之前我们是怎么做测试的?一般有三个方法:

方式弊端
启动整个应用像用户正常操作一样,操作界面调用接口每次测试都需要启动整个项目
在代码某个地方写一个临时入口,例如main方法测试用完就删除不然影响项目运行速度或效率
利用postman工具调用接口每次测试启动服务

在时间允许的情况下,编写单元测试是程序员对代码的自测,这是对自己代码的负责。
写单元测试的两个动机:

  • 保证或验证实现功能。
  • 保护已经实现的功能不被破坏。

Spring Boot引入单元测试

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency>

注解的使用

注解作用
@SpringBootTest获取启动类,加载配置,寻找主配置启动类
@RunWith(SpringRunner.class)让JUnit运行Spring的测试环境,获得Spring环境的上下文的支持
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTest {
}

@SpringBootTest 重要参数

  • args
    应用程序参数,如:args = “–app.test=one”
  • classes
    Spring Boot应用启动入口类名,该参数不指定时由Spring Boot默认查找。
  • webEnvironment
    默认情况下@SpringBootTest不会启动服务器。当测试Web应用时,需指定该参数以便加载上下文环境。

WebEnvironment枚举值说明:

  • MOCK
    默认值,加载WebApplicationContext并提供模拟Web环境。使用此注释时,不会启动嵌入式服务器。
  • RANDOM_PORT
    启动应用并随机监听一个端口。
  • DEFINED_PORT
    启动应用并监听自定义的端口(来自application.properties)或使用默认端口8080。
  • NONE
    ApplicationContext通过使用加载,SpringApplication但不提供任何网络环境(模拟或其他方式)。

工具Junit4

注解的使用

注解作用
@Test编写一般测试用例用
@Test(timeout = 1000)测试方法执行超过1000毫秒后算超时,测试将失败
@Test(expected = Exception.class)测试方法期望得到的异常类,如果方法执行没有抛出指定的异常,则测试失败。
@Before在每个方法测试前执行,一般用来初始化方法(比如我们在测试别的方法时,类中与其他测试方法共享的值已经被改变,为了保证测试结果的有效性,我们会在@Before注解的方法中重置数据)
@After在每个测试方法执行后,在方法执行完成后要做的事情
@BeforeClass在所有测试方法执行前执行
@AfterClass在所有测试方法执行后执行
@Ignore修饰的类或方法会被测试运行器忽略
@RunWith在 Junit 中有很多个 Runner,他们负责调用你的测试代码,每一个 Runner 都有各自的特殊功能,你根据需要选择不同的 Runner 来运行你的测试代码

什么是Mock

在面向对象的程序设计中,模拟对象(英语:mock object)是以可控的方式模拟真实对象行为的假对象。在编程过程中,通常通过模拟一些输入数据,来验证程序是否达到预期结果。

为什么使用Mock对象

使用模拟对象,可以模拟复杂的、真实的对象行为。如果在单元测试中无法使用真实对象,可采用模拟对象进行替代。
spring测试框架提供了两种方式,独立安装和集成Web环境测试(此种方式并不会集成真正的web环境,而是通过相应的Mock API进行模拟测试,无须启动服务器)

Java的Mockito框架

Mockito是一款用于java开发的mock测试框架,用于快速创建和配置mock对象。通过创建外部依赖的 Mock 对象, 然后将此 Mock 对象注入到测试类中,简化有外部依赖的类的测试。

MockMvc的概念

MockMvc是由spring-test包提供,实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,使得测试速度快、不依赖网络环境。同时提供了一套验证的工具,结果的验证十分方便。

接口MockMvcBuilder,提供一个唯一的build方法,用来构造MockMvc。主要有两个实现:StandaloneMockMvcBuilder和DefaultMockMvcBuilder。

StandaloneMockMvcBuilder:指定 WebApplicationContext,它将会从该上下文获取相应的控制器并得到相应的 MockMvc

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserControllerTest  {@Autowiredprivate WebApplicationContext webApplicationContext;private MockMvc mockMvc;@Beforepublic void setUp() throws Exception {mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
} 

DefaultMockMvcBuilder:通过参数指定一组控制器,这样就不需要从上下文获取了

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserControllerTest  {private MockMvc mockMvc;@Beforepublic void setUp() throws Exception {mockMvc = MockMvcBuilders.standaloneSetup(new UserController()).build();} 
}    
// ...
import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;@RunWith(SpringRunner.class)
@SpringBootTest
public class UserControllerTest {@Autowiredprivate WebApplicationContext webApplicationContext;private MockMvc mockMvc;@Beforepublic void setUp() {mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();}@Testpublic void getUser() {mockMvc.perform(get("/v1/users/1").accept(MediaType.APPLICATION_JSON_UTF8)).andExpect(status().isOk()).andExpect(content().string(containsString("\"name\":\"lyTongXue\"")));}} 

MockMVC的基本步骤

(1) mockMvc.perform执行一个请求。

(2) MockMvcRequestBuilders.get(“XXX”)构造一个请求。

(3) ResultActions.param添加请求传值

(4) ResultActions.accept设置返回类型

(5) ResultActions.andExpect添加执行完成后的断言。

(6) ResultActions.andDo添加一个结果处理器,表示要对结果做点什么事情,比如处使用print输出整个响应结果信息。

(7) ResultActions.andReturn表示执行完成后返回相应的结果。

方法名描述
Mockito.mock(classToMock)模拟对象
Mockito.verify(mock)验证行为是否发生
Mockito.when(methodCall).thenReturn(value1).thenReturn(value2)触发时第一次返回value1,第n次都返回value2
Mockito.doThrow(toBeThrown).when(mock).[method]模拟抛出异常。
Mockito.mock(classToMock,defaultAnswer)使用默认Answer模拟对象
Mockito.when(methodCall).thenReturn(value)参数匹配
Mockito.doReturn(toBeReturned).when(mock).[method]参数匹配(直接执行不判断)
Mockito.when(methodCall).thenAnswer(answer))预期回调接口生成期望值
Mockito.doAnswer(answer).when(methodCall).[method]预期回调接口生成期望值(直接执行不判断)
Mockito.spy(Object)用spy监控真实对象,设置真实对象行为
Mockito.doNothing().when(mock).[method]不做任何返回
Mockito.doCallRealMethod().when(mock).[method] //等价于Mockito.when(mock.[method]).thenCallRealMethod();调用真实的方法
reset(mock)重置mock

使用断言

简单的断言说明

方法名描述
assertEquals判断两个对象或两个原始类型是否相等
assertNotEquals判断两个对象或两个原始类型是否不相等
assertSame判断两个对象引用是否指向同一个对象
assertNotSame判断两个相关对象是否不指向同一个对象
assertTrue判断给定的布尔值是否为true
assertFalse判断给定的布尔值是否为false
assertNull判断给定的对象引用是否为null
assertNotNull判断给定的对象引用是否不为null

单元测试生成插件

TestMe插件可以智能分析被测试类的依赖类,结合Mockito+Junit等单元测试框架,生成Mock/InjectMocks依赖关系,自动生成单元测试类。

下载插件
File——>Settings——>Plugins,搜索TestMe,然后install就好了,插件安装完成后需要重启一下。TestMe
我们打开一个类,这个类就是我们即将要作为实验的类。光标定位到代码里,右击鼠标选择Generate…选择TestMe…后弹出Test Class,选择的是Junit4。
在这里插入图片描述

单元测试规范

1、单元测试代码必须写在如下工程目录 src/test/java,不允许写在业务代码目录下。

2、单元测试的基本目标:语句覆盖率达到 70%;核心模块的语句覆盖率和分支覆盖率都要达到 100%。

3、在工程规约的应用分层中提到的 DAO 层,Manager 层,可重用度高的 Service,都应该进行单元测试。

4、编写单元测试代码遵守 BCDE 原则,以保证被测试模块的交付质量。
阿里巴巴 Java 开发手册 \9. 【推荐】编写单元测试代码遵守 BCDE 原则,以保证被测试模块的交付质量。

Border:边界值测试,包括循环边界、特殊取值、特殊时间点、数据顺序等;
Correct:正确的输入,并得到预期的结果;
Design:与设计文档相结合,来编写单元测试;
Error:强制错误信息输入(如:非法数据、异常流程、非业务允许输入等),并得到预期的结果;

5、对于数据库相关的查询,更新,删除等操作,不能假设数据库里的数据是存在的, 或者直接操作数据库把数据插入进去,请使用程序插入或者导入数据的方式来准备数据。

6、和数据库相关的单元测试,可以设定自动回滚机制,不给数据库造成脏数据。或者 对单元测试产生的数据有明确的前后缀标识。

7、对于不可测的代码建议做必要的重构,使代码变得可测,避免为了达到测试要求而书写不规范测试代码。

8、在设计评审阶段,开发人员需要和测试人员一起确定单元测试范围,单元测试最好覆盖所有测试用例。

9、单元测试作为一种质量保障手段,不建议项目发布后补充单元测试用例,建议在项目提测前完成单元测试。

10、为了更方便地进行单元测试,业务代码应避免以下情况:
构造方法中做的事情过多
存在过多的全局变量和静态方法
存在过多的外部依赖
存在过多的条件语句。说明:多层条件语句建议使用卫语句、策略模式、状态模式等方式重构

11、不要对单元测试存在如下误解:
那是测试同学干的事情
单元测试代码是多余的。系统的整体功能与各单元部件的测试正常与否是强相关的
单元测试代码不需要维护,一年半载后,那么单元测试几乎处于废弃状态
单元测试与线上故障没有辩证关系,好的单元测试能够最大限度地规避线上故障

相关文章:

Spring Boot单元测试

什么是单元测试&#xff1f; 单元测试(unit testing)&#xff0c;是指对软件中的最小可测试单元进行检查和验证的过程就叫单元测试。 单元测试是开发人员编写的一小段代码&#xff0c;用于检验被测代码的一个很小的、很明确的(代码) 功能是否正确。执行单元测试就是为了证明某…...

实景三维浪潮翻涌,新技术“席卷”石家庄!

5月11日&#xff0c;“全自主、全流程、全覆盖”2023实景三维新技术研讨会石家庄站暨航测与遥感学术交流会在石家庄凯旋金悦大酒店圆满举行。 本次会议由中国测绘学会、中国地理信息产业协会指导&#xff0c;河北省测绘学会、河北省地理信息产业协会主办&#xff0c;武汉大势智…...

【Python】使用小脚本

本文整理了我在学习和工作中用到的实用python脚本&#xff0c;希望也能帮助到需要的小伙伴~ 文章目录 视频格式转换顺序遍历文件夹中的文件 视频格式转换 安装视频处理库moviepy pip install moviepy安装FFmpeg&#xff08;FFmpeg是一个开源的多媒体框架&#xff0c;moviepy…...

技术日志2023-5-18

1、Java远程调试 可参考&#xff1a;https://kefeng.wang/2018/03/06/idea-remote-debug/ 2、用户中心这样的基础项目有什么用&#xff0c;感觉非常鸡肋。 今天开发讨论中涉及到了用户中心&#xff0c;感觉在项目中使用用户中心只是给业务系统发一个token&#xff0c;业务系…...

JUC之锁

公平锁、非公平锁 公平锁指的是多线程按照申请锁的顺序来获取锁&#xff1b; 非公平锁指的是多线程不按照申请锁的顺序来获取锁。可能会出现优先级反转&#xff08;后者居上&#xff09; 公平锁为了保证线程申请顺序&#xff0c;势必要付出一定的性能代价&#xff0c;因此其吞…...

C++中的 cout 和 printf 用法

文章目录 前言cout & printfexampleprintf输出string字符串总结 前言 C是一种面向对象的编程语言&#xff0c;它继承了C语言的特点&#xff0c;同时也增加了许多新的特性。在C中的cout 和 printf是两种常用的输出函数&#xff0c;它们都可以将数据显示在屏幕上&#xff0c…...

Maven基础使用

Maven 学习目标 理解Maven的用途掌握Maven的基本操作掌握Maven如何创建Web项目 Maven是什么 面临问题 在学习Maven之前&#xff0c;我们先来看一下我们现在做的项目都有哪些问题。假设你现在做了一个crm的系统&#xff0c;项目中肯定要用到一些jar包&#xff0c;比如说myb…...

【C++ 入坑指南】(06)运算符

文章目录 一、算术运算符二、赋值运算符三、比较运算符四、逻辑运算符五、算法题5.1、拆分位数 运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C 内置了丰富的运算符&#xff0c;并提供了以下类型的运算符&#xff1a; 运算符类型作用算术运算符用于处理四则运算赋值…...

了解一下js中的函数式编程

js中的函数式编程是一种编程范式&#xff0c;它将函数作为一等公民来使用。 在函数式编程中&#xff0c;函数是一种特殊的对象&#xff0c;可以赋值给变量、作为参数传递给其他函数、或作为其他函数的返回值。 函数式编程强调了函数的纯函数性&#xff0c;即函数输入相同时&a…...

动态HTTP代理在linux里的使用

动态HTTP代理是一种可以自动切换代理IP地址的代理方式&#xff0c;可以有效地绕过一些限制访问的网站。在Linux系统中&#xff0c;可以使用Privoxy和Proxychains来实现动态HTTP代理。 以下是在Linux中使用动态HTTP代理的步骤&#xff1a; 1. 安装Privoxy和Proxychains 在终端中…...

软考证书值得考吗?怎么考?

软考证书是什么&#xff1f;有什么用处&#xff1f;必须先明确这两个问题&#xff0c;才能有复习和考取的动力。怎么考过&#xff1f;这是第二步要着重解决的问题。今天详细帮助大家分析一下。 软考是国家级考试&#xff0c;具有强大的权威性与公信力。 软考全称为计算机技术…...

超级秘密文件夹忘记密码的解决办法

超级秘密文件夹是一款非常特殊的文件夹加密软件&#xff0c;它来无影去无踪&#xff0c;在安装后不会留下任何痕迹&#xff0c;只能通过软件热键才能打开。那么如果在使用过程中忘记了密码&#xff0c;这时我们该怎么办呢&#xff1f;下面我们就来了解一下。 首先&#xff0c;我…...

脑的物理系统

⼤脑模块化 人脑是一个复杂的网络&#xff0c;一般将大脑划分为不同的区域&#xff08;即节点&#xff09;&#xff0c;并使用某种方法表征大脑区域之间的关系&#xff08;即连接的边&#xff09;来构建人脑网络。在功能磁共振成像&#xff08;fMRI&#xff09;数据的网络模型…...

1054. 距离相等的条形码(leetcode,堆问题,priority_queue)-------------------c++实现

1054. 距离相等的条形码&#xff08;leetcode,堆问题&#xff0c;priority_queue&#xff09;-------------------c实现 题目表述 在一个仓库里&#xff0c;有一排条形码&#xff0c;其中第 i 个条形码为 barcodes[i]。 请你重新排列这些条形码&#xff0c;使其中任意两个相…...

QT开发实战-动态壁纸软件

动态壁纸软件开发 项目源代码在下面链接获取: ----------------------------- 开发者:CodeSharkSJ 希望此项目能加强你对Qt的应用 文章目录 项目图与开发环境核心技术原理自定义窗口程序UI布局背景绘制样式表基本实现QWebEngineQMedia使用系统托盘隐藏记忆功能应用程序打包 …...

Netty核心组件模块(一)

1.Bootstrap和ServerBootstrap 1>.Bootstrap意思是引导,一个Netty应用通常由一个Bootstrap开始,主要作用是配置整个Netty程序,串联各个组件,Netty中Bootstrap类是客户端程序的启动引导类,ServerBootstrap是服务端启动引导类; 2>.常见的方法有: ①.public ServerBootstr…...

Robot Framework+Jenkins持续集成UI自动化项目

使用Robot Framework框架可进行Web端和APP端的UI自动化测试&#xff0c;为方便定时执行&#xff0c;可将Robot Framework的自动化项目持续集成至Jenkins平台&#xff0c;具体的操作步骤如下&#xff1a; 安装Jenkins的步骤如下&#xff1a; 手把手教小白安装Jenkins_程序员馨馨…...

【ROS】ROS1编程速览

1、简述 很多项目已经转向ROS2&#xff0c;本人作为ROS小白从ROS1开始学起&#xff0c;但是不会深入学习ROS1&#xff0c;只一带而过。 下面只了解一些ROS1中的概念和基本编程接口。 ROS1中有两种通信模式&#xff1a;话题模式和服务模式&#xff0c;区别如下 2、话题模式 …...

探索智能化:TOOM解析未来稿件校验系统的技术进展与应用展望

在信息时代&#xff0c;随着大数据、人工智能和自然语言处理等技术的快速发展&#xff0c;稿件校验系统正朝着智能化的方向迈进。智能化的稿件校验系统能够更准确、高效地检测虚假信息、抄袭行为以及提升文章质量。本文将探讨智能化稿件校验系统的技术进展与应用展望&#xff0…...

Java程序员从青铜到王者,不同段位的薪资和技能变化

想要薪资高&#xff0c;段位就得跟上&#xff0c;对于Java程序员来说&#xff0c;从青铜到王者&#xff0c;需要经历多个阶段&#xff0c;每个阶段需要掌握的技能都不一样。 今天&#xff0c;我们一起来看看每个段位都有什么特点、需要具备哪些“大杀”技能&#xff0c;也看看…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...