年底,家庭和工作的双重忙碌,让人一直在路上,而每次静心思考总会有未完成的遗憾。安静的夜晚,总是那么头脑请详细,很累也很高兴,2017年的自有框架改造终于一个通宵的过程中,又迈进了一大步,service层的整体模型全部构造完成。截至目前,docker转换、基础资源集群自动化,service层的开发测试技术框架调整均完成。由于service层的文档碎片化比较高,稍后整理完毕再发,先发刚参考前人汇总过的测试case的技术文档。
UDP统一开发平台
测试模块_技术参考文档
一、概述
在统一开发平台框架中,考虑敏捷开发的模式,有意向于测试驱动开发,在组件层、服务层等共用底层构建中,构建测试驱动开发,测试与开发并行的模式。通过测试案例代码控制共用层的变更。在技术上,采用junit 4+mockito 2+EclEmma,对测试的质量进行自动化管理。先简单说一下为什么要写测试用例:
1). 可以避免测试点的遗漏,为了更好的进行测试,可以提高测试效率
2). 可以自动测试,可以在项目打包前进行测试校验
3). 可以及时发现因为修改代码导致新的问题的出现,并及时解决
Mock测试概念:测试过程中,对那些不容易构建的对象用一个虚拟对象来代替测试的方法。可以在接口代码实现之前,通过mock提前构建模拟测试代码。等同于测试代码提前开始编写,模拟并针对模拟测试,使研发、测试团队之间不需要互相等待。Mockito区别于其他模拟框架的地方主要是允许开发者在没有建立“预期”时验证被测系统的行为。
Mockito 都因为可以极大地简化单元测试的书写过程而被许多人应用在自己的工作中,但是这两种 Mock 工具都不可以实现对静态函数、构造函数、私有函数、Final 函数以及系统函数的模拟,但是这些方法往往是我们在大型系统中需要的功能。
TDD:测试驱动开发。
二、引入junit+mockito+EclEmma
Maven引入mockito2.13.0
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.13.0</version>
<scope>test</scope>
</dependency>
Maven引入junit4.12
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
IDE安装EclEmma
打开Eclipse,点击Help → Install New Software →输入update.eclemma.org,安装软件即可。然后通过Coverage来运行spring boot入口类。执行完毕之后,正在编辑 java 的窗口将会,EclEmma 用不同的色彩标示了源代码的测试情况。其中,绿色的行表示该行代码被完整的执行,红色部分表示该行代码根本没有被执行,而黄色的行表明该行代码部分被执行。黄色的行通常出现在单行代码包含分支的情况。EclEmma 还提供了一个单独的视图来统计程序的覆盖测试率。可以选择行覆盖(Line),分支(Branch)覆盖等多种覆盖率检测标准。
三、Junit应用
1. 详细步骤
1) 通过maven引入同版本的spring-boot-starter-test包。
2) 构建springboot主类,在使用时,再次提醒一定要查阅最新版本的文档。旧注解内容SpringJUnit4ClassRunner.clas\SpringApplicationConfiguration已被废弃。

2. 参数化测试
测试时加入参数类,注意注解、参数类的构造、以及初始化。

3. 打包测试
新增测试类,将其他单体测试类集合在一起。

4. http测试
仿照POST请求进行http测试。

5. 捕获输出
使用 OutputCapture 来捕获指定方法开始执行以后的所有输出,包括System.out输出和Log日志。OutputCapture 需要使用@Rule注解,并且实例化的对象需要使用public修饰。

6. Junit常用注解
@Before:初始化方法
@After:释放资源
@Test:测试方法,在这里可以测试期望异常和超时时间
@Ignore:忽略的测试方法
@BeforeClass:针对所有测试,只执行一次,且必须为static void
@AfterClass:针对所有测试,只执行一次,且必须为static void
@RunWith:指定使用的单元测试执行类
7. Junit测试用例执行顺序
@BeforeClass ==> @Before ==> @Test ==> @After ==> @AfterClass过程:就是 先加载模拟的环境,再进行测试。
四、Mock相关
1. 引入
Mocke的引入参考前面maven引入方式。
2. 初始化
在@before注解的方法中,初始化mockito的所有模拟对象。然后在创建模拟对象,创建mock对象不能对final,Anonymous ,primitive类进行mock。
@Before
public void setUp() throws Exception {
//初始化测试用例类中由Mockito的注解标注的所有模拟对象
MockitoAnnotations.initMocks(this);
}

3. 模拟对象
mock(Class classToMock);
mock(Class classToMock, String name)
mock(Class classToMock, Answer defaultAnswer)
mock(Class classToMock, MockSettings mockSettings)
mock(Class classToMock, ReturnValues returnValues)
例如: LinkedList mockedList = mock(LinkedList.class);
4. 设置对象调用的预期返回值(待扩展)
该部分内容使用上比较隐晦,参考https://www.cnblogs.com/zishi/p/6780719.html
当mock对象被调用时,返回value的例子:when(mock.someMethod()).thenReturn(value) 。
Answer 是个泛型接口。到调用发生时将执行这个回调,通过 Object[] args = invocation.getArguments();可以拿到调用时传入的参数,通过 Object mock = invocation.getMock();可以拿到mock对象。有些方法可能接口的参数为一个Listener参数,如果我们使用Answer打桩,我们就可以获取这个Listener,并且在Answer函数中执行对应的回调函数,这对我们了解函数的内部执行过成有很大的帮助。
Spy函数:你可以为真实对象创建一个监控(spy)对象,当你使用这个spy对象时,真实的对象也会被调用,除非它的函数被打桩。你应该尽量少的使用spy对象,使用时也需要小心,例如spy对象可以用来处理遗留代码,
5. 参数匹配器
Matchers类内加你有很多参数匹配器 anyInt、anyString、anyMap.....Mockito类继承于Matchers,Stubbing时使用内建参数匹配器。需要注意的是:如果使用参数匹配器,那么所有的参数都要使用参数匹配器,不管是stubbing还是verify的时候都一样。

由于Eclipse对于import static的支持很差,你可能还需要记得加上下图中内容:
五、参考文献
Mockito2优势:https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2
Spring boot +junit例子:http://www.60kb.com/post/45.html
Mockito官网: http://site.mockito.org/
5分钟了解Mockito:http://liuzhijun.iteye.com/blog/1512780
Mockito简单介绍及示例:http://blog.csdn.net/huoshuxiao/article/details/6107835
Mockito浅谈:http://www.jianshu.com/p/77db26b4fb54
单元测试利器-Mockito 中文文档:http://blog.csdn.net/bboyfeiyu/article/details/52127551
Mockito使用指南 :http://blog.csdn.net/shensky711/article/details/52771493
JUnit+Mockito 单元测试(二):http://blog.csdn.net/zhangxin09/article/details/42422643





