前言
这次来介绍下Spring Boot中对单元测试的整合使用,本篇会通过以下4点来介绍,基本满足日常需求
Service层单元测试
Controller层单元测试
新断言assertThat使用
单元测试的回滚
正文
Spring Boot中引入单元测试很简单,依赖如下:
本篇实例Spring Boot版本为1.5.9.RELEASE,引入spring-boot-starter-test后,有如下几个库: • JUnit — The de-facto standard for unit testing Java applications. • Spring Test & Spring Boot Test — Utilities and integration test support for Spring Boot applications. • AssertJ — A fluent assertion library. • Hamcrest — A library of matcher objects (also known as constraints or predicates). • Mockito — A Java mocking framework. • JSONassert — An assertion library for JSON. • JsonPath — XPath for JSON.
Service单元测试
Spring Boot中单元测试类写在在src/test/java目录下,你可以手动创建具体测试类,如果是IDEA,则可以通过IDEA自动创建测试类,如下:
自动生成测试类如下:
Service层单元测试
然后再编写创建好的测试类,具体代码如下:
上面就是最简单的单元测试写法,顶部只要 @RunWith(SpringRunner.class)和 SpringBootTest即可,想要执行的时候,鼠标放在对应的方法,右键选择run该方法即可。
测试用例中我使用了assertThat断言,下文中会介绍,也推荐大家使用该断言。
Controller单元测试
上面只是针对Service层做测试,但是有时候需要对Controller层(API)做测试,这时候就得用到MockMvc了,你可以不必启动工程就能测试这些接口。
MockMvc实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快、不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便。
Controller类:
这里我们也自动创建一个Controller的测试类,具体代码如下:
上面实现了基本的增删改查的测试用例,使用MockMvc的时候需要先用MockMvcBuilders使用构建MockMvc对象,如下:
因为拦截器那边会判断是否登录,所以这里我注入了一个用户,你也可以直接修改拦截器取消验证用户登录,先测试完再开启。
这里拿一个例子来介绍一下MockMvc简单的方法
mockMvc.perform执行一个请求
MockMvcRequestBuilders.get("/user/1")构造一个请求,Post请求就用.post方法
contentType(MediaType.APPLICATIONJSONUTF8)代表发送端发送的数据格式是 application/json;charset=UTF-8
accept(MediaType.APPLICATIONJSONUTF8)代表客户端希望接受的数据类型为 application/json;charset=UTF-8
session(session)注入一个session,这样拦截器才可以通过
ResultActions.andExpect添加执行完成后的断言
ResultActions.andExpect(MockMvcResultMatchers.status().isOk())方法看请求的状态响应码是否为200如果不是则抛异常,测试不通过
andExpect(MockMvcResultMatchers.jsonPath("$.author").value("嘟嘟MD独立博客"))这里jsonPath用来获取author字段比对是否为 嘟嘟MD独立博客,不是就测试不通过
ResultActions.andDo添加一个结果处理器,表示要对结果做点什么事情,比如此处使用MockMvcResultHandlers.print()输出整个响应结果信息
本例子测试如下:
mockMvc 更多例子可以本篇下方参考查看
新断言assertThat使用
JUnit 4.4 结合 Hamcrest 提供了一个全新的断言语法——assertThat。程序员可以只使用 assertThat 一个断言语句,结合 Hamcrest 提供的匹配符,就可以表达全部的测试思想,我们引入的版本是Junit4.12所以支持assertThat。
assertThat 的基本语法如下:
清单 1 assertThat 基本语法
assertThat( [value], [matcher statement] );
value 是接下来想要测试的变量值;
matcher statement 是使用 Hamcrest 匹配符来表达的对前面变量所期望的值的声明,如果 value 值与 matcher statement 所表达的期望值相符,则测试成功,否则测试失败。
assertThat 的优点
优点 1:以前 JUnit 提供了很多的 assertion 语句,如:assertEquals,assertNotSame,assertFalse,assertTrue,assertNotNull,assertNull 等,现在有了 JUnit 4.4,一条 assertThat 即可以替代所有的 assertion 语句,这样可以在所有的单元测试中只使用一个断言方法,使得编写测试用例变得简单,代码风格变得统一,测试代码也更容易维护。
优点 2:assertThat 使用了 Hamcrest 的 Matcher 匹配符,用户可以使用匹配符规定的匹配准则精确的指定一些想设定满足的条件,具有很强的易读性,而且使用起来更加灵活。如清单 2 所示:
清单 2 使用匹配符 Matcher 和不使用之间的比较
优点 3:assertThat 不再像 assertEquals 那样,使用比较难懂的“谓宾主”语法模式(如:assertEquals(3, x);),相反,assertThat 使用了类似于“主谓宾”的易读语法模式(如:assertThat(x,is(3));),使得代码更加直观、易读。
优点 4:可以将这些 Matcher 匹配符联合起来灵活使用,达到更多目的。如清单 3 所示:
清单 3 Matcher 匹配符联合使用
优点 5:错误信息更加易懂、可读且具有描述性(descriptive) JUnit 4.4 以前的版本默认出错后不会抛出额外提示信息,如:
assertTrue( s.indexOf("developer") > -1 || s.indexOf("Works") > -1 );
如果该断言出错,只会抛出无用的错误信息,如:junit.framework.AssertionFailedError:null。 如果想在出错时想打印出一些有用的提示信息,必须得程序员另外手动写,如:
assertTrue( "Expected a string containing 'developer' or 'Works'",
s.indexOf("developer") > -1 || s.indexOf("Works") > -1 );
非常的不方便,而且需要额外代码。 JUnit 4.4 会默认自动提供一些可读的描述信息,如清单 4 所示: 清单 4 JUnit 4.4 默认提供一些可读的描述性错误信息
如何使用 assertThat
JUnit 4.4 自带了一些 Hamcrest 的匹配符 Matcher,但是只有有限的几个,在类 org.hamcrest.CoreMatchers 中定义,要想使用他们,必须导入包 org.hamcrest.CoreMatchers.*。
清单 5 列举了大部分 assertThat 的使用例子:
单元测试回滚
单元个测试的时候如果不想造成垃圾数据,可以开启事物功能,记在方法或者类头部添加 @Transactional
注解即可,如下:
这样测试完数据就会回滚了,不会造成垃圾数据。如果你想关闭回滚,只要加上 @Rollback(false)注解即可。 @Rollback表示事务执行完回滚,支持传入一个参数value,默认true即回滚,false不回滚。
如果你使用的数据库是Mysql,有时候会发现加了注解 @Transactional 也不会回滚,那么你就要查看一下你的默认引擎是不是InnoDB,如果不是就要改成InnoDB。
MyISAM与InnoDB是mysql目前比较常用的两个数据库存储引擎,MyISAM与InnoDB的主要的不同点在于性能和事务控制上。这里简单的介绍一下两者间的区别和转换方法:
MyISAM:MyISAM是MySQL5.5之前版本默认的数据库存储引擎。MYISAM提供高速存储和检索,以及全文搜索能力,适合数据仓库等查询频繁的应用。但不支持事务、也不支持外键。MyISAM格式的一个重要缺陷就是不能在表损坏后恢复数据。
InnoDB:InnoDB是MySQL5.5版本的默认数据库存储引擎,不过InnoDB已被Oracle收购,MySQL自行开发的新存储引擎Falcon将在MySQL6.0版本引进。InnoDB具有提交、回滚和崩溃恢复能力的事务安全。但是比起MyISAM存储引擎,InnoDB写的处理效率差一些并且会占用更多的磁盘空间以保留数据和索引。尽管如此,但是InnoDB包括了对事务处理和外来键的支持,这两点都是MyISAM引擎所没有的。
MyISAM适合:(1)做很多count 的计算;(2)插入不频繁,查询非常频繁;(3)没有事务。
InnoDB适合:(1)可靠性要求比较高,或者要求事务;(2)表更新和查询都相当的频繁,并且表锁定的机会比较大的情况。(4)性能较好的服务器,比如单独的数据库服务器,像阿里云的关系型数据库RDS就推荐使用InnoDB引擎。
修改默认引擎的步骤
查看MySQL当前默认的存储引擎:
mysql> show variables like '%storage_engine%';
你要看user表用了什么引擎(在显示结果里参数engine后面的就表示该表当前用的存储引擎):
mysql> show create table user;
将user表修为InnoDB存储引擎(也可以此命令将InnoDB换为MyISAM):
mysql> ALTER TABLE user ENGINE=INNODB;
如果要更改整个数据库表的存储引擎,一般要一个表一个表的修改,比较繁琐,可以采用先把数据库导出,得到SQL,把MyISAM全部替换为INNODB,再导入数据库的方式。 转换完毕后重启mysql
service mysqld restart
总结
到此为止,Spring Boot整合单元测试就基本完结,关于MockMvc以及assertThat的用法大家可以继续深入研究。后续会整合Swagger UI这个API文档工具,即提供API文档又提供测试接口界面,相当好用。
想要查看更多Spring Boot干货教程,可前往:Spring Boot干货系列总纲
参考
Junit学习笔记之五:MockMVC探索 JUnit 4.4 新特性
源码下载
( ̄︶ ̄)↗[相关示例完整代码] - chapter12==》Spring Boot干货系列:(十二)Spring Boot使用单元测试
一直觉得自己写的不是技术,而是情怀,一篇篇文章是自己这一路走来的痕迹。靠专业技能的成功是最具可复制性的,希望我的这条路能让你少走弯路,希望我能帮你抹去知识的蒙尘,希望我能帮你理清知识的脉络,希望未来技术之巅上有你也有我。
————————————————
版权声明:本文为CSDN博主「嘟爷java超神学堂」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/vqhgWJl9EUB/article/details/78930280