Spring Boot单元测试

news2024/11/20 17:39:40

什么是单元测试?

单元测试(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  {
    @Autowired
    private WebApplicationContext webApplicationContext;
    private MockMvc mockMvc;
    @Before
    public void setUp() throws Exception {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
} 

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

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserControllerTest  {
    private MockMvc mockMvc;
    @Before
    public 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 {

    @Autowired
    private WebApplicationContext webApplicationContext;
    private MockMvc mockMvc;

    @Before
    public void setUp() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

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

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

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

相关文章

Java面试知识点(全)- Java并发- Java并发基础一

Java面试知识点(全) 导航&#xff1a; https://nanxiang.blog.csdn.net/article/details/130640392 注&#xff1a;随时更新 多线程解决什么问题 CPU、内存、I/O 设备的速度是有极大差异的&#xff0c;为了合理利用 CPU 的高性能&#xff0c;平衡这三者的速度差异&#xff0c…

PMP课堂模拟题目及解析(第11期)

101. 一家咨询公司的负责人启动一个项目来扩大公司提供的服务数量&#xff0c;这公司具有竞争优势、出色的企业知识以及卓越的声誉&#xff0c;高管团队担心与增加新服务相关的负面业务结果的可能性。若要评估负面业务结果的可能性和影响&#xff0c;项目经理应该使用什么&…

matlab写入txt文件进行自动化测试总结:fopen、fclose和fprintf的用法

前言 日常学习的过程中使用了matlab读写txt文件&#xff0c;记录一下基本函数的使用&#xff0c;本文主要介绍了fopen、fclose和fprintf几个函数&#xff0c;这些主要是面向txt格式的文件保存数据。还有其他几个函数&#xff0c;比如fread和fwrite&#xff0c;用过但是他们是针…

【dcdc】AP2813 DCDC降压恒流芯片 两路输出 一路恒流 一路瀑闪 电动摩托汽车灯方案

1&#xff0c;方案来源&#xff1a;深圳市世微半导体有限公司 汤巧 2&#xff0c;产品描述 AP2813 是一款双路降压恒流驱动器,高效率、外围简单、内置功率管&#xff0c;适用于 5-80V 输入的高精度降压 LED 恒流驱动芯片。内置功率管输出最大功率可达12W&#xff0c;最大电流…

图神经网络+强化学习

访问【WRITE-BUG数字空间】_[内附完整源码和文档] 车辆路径规划问题&#xff08;VRP&#xff09;是运筹优化领域最经典的优化问题之一。在此问题中&#xff0c;有若干个客户对某种货物有一定量的需求&#xff0c;车辆可以从仓库取货之后配送到客户手中。客户点与仓库点组成了一…

DSP_TMS320F28377D_一键烧写多核程序

以前在开发和调试TMS320F28377D的双核程序的时候&#xff0c;总是在烧写CPU1程序时&#xff0c;自动把CPU2的程序也烧写了&#xff0c;但往CPU2里面烧写的是CPU1的程序&#xff0c;烧写完进入在线仿真模式的时候&#xff0c;还需要手动重新选择CPU2要烧写的程序&#xff0c;重新…

谈谈Netty线程模型

大家好&#xff0c;我是易安&#xff01; Netty是一个高性能网络应用框架&#xff0c;应用非常普遍&#xff0c;目前在Java领域里&#xff0c;Netty基本上成为网络程序的标配了。Netty框架功能丰富&#xff0c;也非常复杂&#xff0c;今天我们主要分析Netty框架中的线程模型&am…

【数据分享】2014-2023年全国监测站点的逐年空气质量数据(15个指标\shp\excel格式)

空气质量的好坏反映了空气的污染程度&#xff0c;在各项涉及城市环境的研究中&#xff0c;空气质量都是一个十分重要的指标。空气质量是依据空气中污染物浓度的高低来判断的。 我们发现学者王晓磊在自己的主页里面分享了2014年5月以来的全国范围的到站点的逐时空气质量数据&am…

网络安全--红队资源大合集

红队攻击的生命周期&#xff0c;整个生命周期包括&#xff1a; 信息收集、攻击尝试获得权限、持久性控制、权限提升、网络信息收集、横向移动、数据分析&#xff08;在这个基础上再做持久化控制&#xff09;、在所有攻击结束之后清理并退出战场。 重点提醒&#xff1a;本项目…

JVM内存区域(一)

运行时数据区域 ** 线程私有的&#xff1a; 程序计数器虚拟机栈本地方法栈线程共享的&#xff1a; 线程共享的&#xff1a; 堆方法区直接内存 (非运行时数据区的一部分) 程序计数器 程序计数器是一块较小的内存空间&#xff0c;可以看作是当前线程所执行的字节码的行号指示…

15-02 身份安全

身份安全——认证 目录管理系统 身份认证 你知道什么&#xff1a;密码、PIN、密码短语你拥有什么&#xff1a;硬令牌、智能卡、USB卡、手机APP指纹、声纹、脸纹、虹膜 授权和访问控制 访问控制 访问控制原则 最小特权&#xff1a;安全管理员禁止访问任何资源默认拒绝&…

【005】C++数据类型之实型(浮点数)、有符号数以及无符号数

C数据类型之实型、有符号数以及无符号数 引言一、实型&#xff08;浮点数&#xff09;1.1、实型常量1.2、实型变量 二、有符号数三、无符号数总结 引言 &#x1f4a1; 作者简介&#xff1a;专注于C/C高性能程序设计和开发&#xff0c;理论与代码实践结合&#xff0c;让世界没有…

Eolink 出席 QECon 深圳站,共同探讨软件质量和效能发展

5月12日至13日&#xff0c;由 QECon 组委会和深圳市软件行业协会联合主办的「QECon全球软件质量&效能大会」成功召开&#xff0c;作为国内 API 全生命周期解决方案的领军者&#xff0c;Eolink 受邀参加此次大会。 大会中&#xff0c;Eolink SaaS 产品负责人崔嘉杰、高级售…

《思考致富》不应该指望不经历“暂时的失败”便能发财

目录 作者简介 经典摘录 机遇有个狡猾的习惯&#xff0c;喜欢从后门悄悄溜进来&#xff0c;往往还喜欢以灾难或暂时失败的方式乔装露面 离金矿仅有三英尺远 欲望&#xff1a;成就一切的起点&#xff08;通往致富之路的第一步&#xff09; 信念&#xff1a;在脑海里目睹并坚…

网络安全萌新先学什么?后学什么?

在选择网络安全行业之前&#xff0c;我们要弄清楚&#xff0c;要问一下自己的内心&#xff0c;自己为什么要进入这个行业&#xff1f;每个人的答案肯定是不一样的。 肯定有人会说&#xff1a;这个行业比很多其他行业更赚钱 有人会说&#xff1a;对网络安全技术非常感兴趣 有人会…

Web3和低代码开发:下一代Web应用开发的合作与创新

Web3作为区块链技术的一部分&#xff0c;被认为是下一代互联网技术的主要方向。与此同时&#xff0c;低代码开发作为快捷而高效的软件创建工具&#xff0c;也一直得到广泛关注。那么&#xff0c;Web3和低代码开发如何合作&#xff0c;激发出下一代Web应用开发的新生力量呢&…

前端性能优化:如何提高页面加载速度和用户体验

第一章&#xff1a;介绍 当今互联网时代&#xff0c;网站的性能对于用户体验至关重要。一个快速加载的网页不仅能提高用户的满意度&#xff0c;还能增加页面的转化率。而在前端开发中&#xff0c;性能优化是一个永恒的话题。本篇博客将为大家分享一些关于前端性能优化的技巧和…

红色元宇宙数字展厅:三维构建身临其境的红色历史之旅

导语&#xff1a;红色&#xff0c;是中国革命的象征&#xff0c;是我们历史中最为壮丽的篇章之一。然而&#xff0c;随着时间的推移&#xff0c;许多珍贵的红色记忆逐渐模糊&#xff0c;年轻一代对于红色历史的认知也渐行渐远。 红色元宇宙数字展厅&#xff0c;作为一种全新的互…

2023年软件测试前景?自动化测试的未来?我的测试之路高歌猛进...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 Python自动化测试&…

网络计算模式复习(五)

结构化P2P&#xff1a;直接根据查询内容的关键字定位其索引的存放节点 DHT算法 将内容索引抽象为<K,V>对 K是内容关键字的Hash摘要&#xff1a;KHash(key) V是存放内容的实际位置&#xff0c;例如节点IP地址等所有的<K,V>对组成一张大的Hash表&#xff0c;该表存…