文章来源:https://dwz.cn/bC1N6R0v
原文作者:美码师
目标
- 了解 单元测试的背景
- 了解如何 利用 springboot 实现接口的测试
- 了解如何 利用 mokito 做代码的 mock
一、About 单元测试
单元测试其实是一种廉价的技术,是由开发者创建运行测试代码,用于对程序模块(软件设计的最小单位)进行正确性检验的一种做法。 而所谓的最小单元,就是指应用的最小可测试部件。 在面向对象领域,最小单元对应于类的某个成员方法。
通常意义的单元测试会用于验证某场景、某条件下某方法的行为结果,举个例子:
我想验证
单元测试的初衷,是对各个相互独立,互不影响的基本单元基线测试,以此来保证核心代码的质量。
每一段单元测试代码,都一定会包含几个部分:
- Arrange 用于初始化一些被测试方法需要的参数或依赖的对象。
- Act方法 用于调用被测方法进行测试。
- Assert
用于验证测试方法是否按期望执行或者结果是否符合期望值
See !并不是很复杂,可是大多数开发者并不喜欢做单元测试。 而且,有一个现象很有意思,水平越高的程序员,越不喜欢写测试代码,why?
“ 因为单元测试,主要是用来防低级程序员挖坑的啊 ”
这句话不是我说的,但却代表了相当一部分程序员的心声..
那么,单元测试到底要不要做,并不是本文要讨论的问题。 建议大家阅读下 《单元测试之道-Java版本》 (程序员修炼三部曲系列)这边书,看完后再做出自己的理解。
为了测试一座桥梁,不应该只在晴朗的天气,开一辆汽车从桥中间穿过,就认为已经完成了对桥梁的测试
二、About Junit
接下来,要说一说 Junit框架,这个是最流行的Java 单元测试框架。
Junit 创建者是 Kent Beck 和 Erich Gamma,自其出现以来,Junit 生态圈已经非常庞大。 大量的应用程序、开发框架都以 Junit 作为标准的的基础测试组件,这当然也包括 Spring系列的框架。
一个典型的Junit单元测试类:
说明
这几个注解还是比较容易理解的,需要注意的只是 @BeforeClass 和 @Before,前者是一个静态方法, 会在整个测试用例类开始前执行,仅一次;
而后者则是在方法测试之前触发,可能会执行多次。
为了更清晰的理解Junit 是怎么运作,下面展示一个源码片段:
这是早期版本的TestCase类其中的一段实现,与我们所说的思路是基本一致的! 然而,基于注解的实现是由 Junit4提供的,在有兴趣的话可以深入看看源码。
关键词
TestCase、JUnit4TestAdapter、BlockJUnit4ClassRunner
三、SpringBoot-单元测试
SpringBoot 提供了 spring-boot-starter-test 用于实现单元测试。
项目依赖
测试样例
说明
SpringRunner继承于SpringJUnit4ClassRunner,这是Spring框架基于Junit实现的基础类。
如果还记得前面提到的 BlockJUnit4ClassRunner,应该不难猜到,Spring 的实现类集成了该类。
那么,SpringRunner 做了什么? 什么也没有,只是一个名称的修正而已(论命名的重要性)
@SpringBootTest的作用
其代码注释如下:
要点
- 默认会使用SpringBootContextLoader类用于上下文加载, 这个类将会使用所配置的SpringBootApplication实体类作为入口,加载配置并初始化Spring上下文环境;
- 可以支持自定义的配置,通过 Environment 属性设置;
- 支持不同的 web 环境模式,可以是固定端口、随机端口、无端口几种模式。
关键词
SpringRunner、SpringBootTest、SpringBootContextLoader
四、Mock测试
Mock 测试的使用场景在于,被测试模块(方法)依赖于外部系统(web服务、中间件或是数据库)。
我们需要提供一种快速验证本地实现逻辑的策略,那就是 Mock,也称为打桩。
如上图,A 模块依赖于 B 模块,在 B 模块不可达的时候,我们对 依赖接口进行了 Mock。这样在执行测试时,不需要真实的 B 模块便可完成测试。
下面我们要用到的 Mock 组件叫 Mockito
springboot-starter-test 自带了对于 mockito 的依赖,下面看一段代码:
看到了吗,利用 Mockito 可以实现你想要的 Mock效果,如下:
然而,在进行 mock 方法时,需要使用 standaloneSetup 的模式, 否则 mockito 无法工作。
关键词
Mockito、MockMvcBuilders
五、最后
细心的读者会发现,前面讲了单元测试的对象,是指软件设计的最小单位(方法),可是为什么到了 SpringBoot 的部分却都是对于API(Controller层)的测试呢?
到底我们的单元测试应该针对内部实现的某个单元,比如 DAO/Service方法,还是针对接口(API Interface)?
笔者认为,这点并没有绝对的好坏之分,关键在于取舍。
单元测试是软件工程领域的概念,而软件项目是分很多种类型的,比如在早期的软件工程中,就有不少的基于C/S架构的程序,这类程序的体积相对庞大,往往需要对大量模块级的方法进行单元测试;
我自己是一名从事了多年开发的Java老程序员,辞职目前在做自己的Java私人定制课程,今年年初我花了一个月整理了一份最适合2019年学习的Java学习干货,从最基础的JavaSE到Spring各种框架都有整理,送给每一位Java小伙伴,想要获取的可以关注我的头条号并在后台私信我:Java,即可免费获取。
本文来自投稿,不代表本人立场,如若转载,请注明出处:http://www.sosokankan.com/article/1823725.html