ava单元测试技巧之owerock

丰富的线上&线下活动,深入探索云世界

做任务,得社区积分和周边

资深技术专家手把手带教

技术交流,直击现场

让创作激发创新

海量开发者使用工具、手册,免费下载

极速、全面、稳定、安全的开源镜像

开发手册、白皮书、案例集等实战精华

高德的技术大佬向老师在谈论方法论时说到:“复杂的问题要简单化,简单的问题要深入化。”这句话让我感触颇深,这何尝不是一套编写代码的方法——把一个复杂逻辑拆分为许多简单逻辑,然后把每一个简单逻辑进行深入实现,最后把这些简单逻辑整合为复杂逻辑,总结为八字真言即是“化繁为简,由简入繁”。编写Java单元测试用例,其实就是把“复杂的问题要简单化”——即把一段复杂的代码拆解成一系列简单的单元测试用例;写好Java单元测试用例,其实就是把“简单的问题要深入化”——即学习一套方法、总结一套模式并应用到实践中。这里,作者根据日常的工作经验,总结了一些Java单元测试技巧,以供大家交流和学习。

PowerMock是一个扩展了其它如EasyMock等mock框架的、功能更加强大的框架。PowerMock使用一个自定义类加载器和字节码操作来模拟静态方法、构造方法、final类和方法、私有方法、去除静态初始化器等等。

这里,用List举例,模拟一个不存在的列表,但是返回的列表大小为100。

两种模式都用于模拟对象方法,在mock实例下使用时,基本上是没有差别的。但是,在spy实例下使用时,when().thenReturn()模式会执行原方法,而doReturn().when()模式不会执行原方法。测试服务类:

使用when().thenReturn()模式:

在测试过程中,将会打印出"调用获取用户数量方法"日志。

使用doReturn().when()模式:

在测试过程中,不会打印出"调用获取用户数量方法"日志。

4.4. whenNew模拟构造方法

在执行单元测试时,有时候并不关心传入的参数的值,可以使用参数匹配器。

Mockito的AdditionalMatchers类提供了一些很少使用的参数匹配器,我们可以进行参数大于(gt)、小于(lt)、大于等于(geq)、小于等于(leq)等比较操作,也可以进行参数与(and)、或(or)、非(not)等逻辑计算等。

验证是确认在模拟过程中,被测试方法是否已按预期方式与其任何依赖方法进行了交互。

格式:

用途:

用于模拟对象方法,直接返回期望的值、异常、应答,或调用真实的方法,无需执行原始方法。

案例:

除times外,Mockito还支持atLeastOnce、atLeast、only、atMostOnce、atMost等次数验证器。

Mockito没有静态方法的验证方法,但是PowerMock提供这方面的支持。

通过模拟方法stub(存根),也可以实现模拟私有方法。但是,只能模拟整个方法的返回值,而不能模拟指定参数的返回值。

这里,也可以用Method那套方法进行模拟和验证方法。

PowerMock为了更好地支持SpringMVC/SpringBoot项目,提供了一系列的注解,大大地简化了测试代码。

指定JUnit 使用 PowerMock 框架中的单元测试运行器。

当需要模拟final类、final方法或静态方法时,需要添加@PrepareForTest注解,并指定方法所在的类。如果需要指定多个类,在{}中添加多个类并用逗号隔开即可。

@Mock注解创建了一个全部Mock的实例,所有属性和方法全被置空(0或者null)。

@Spy注解创建了一个没有Mock的实例,所有成员方法都会按照原方法的逻辑执行,直到被Mock返回某个具体的值为止。

注意:@Spy注解的变量需要被初始化,否则执行时会抛出异常。

@InjectMocks注解创建一个实例,这个实例可以调用真实代码的方法,其余用@Mock或@Spy注解创建的实例将被注入到用该实例中。

为了解决使用PowerMock后,提示ClassLoader错误。

【强制】好的单元测试必须遵守AIR原则。 说明:单元测试在线上运行时,感觉像空气(AIR)一样感觉不到,但在测试质量的保障上,却是非常关键的。好的单元测试宏观上来说,具有自动化、独立性、可重复执行的特点。

A:Automatic(自动化)

I:Independent(独立性)

R:Repeatable(可重复)

【强制】单元测试是可以重复执行的,不能受到外界环境的影响。

说明:单元测试通常会被放到持续集成中,每次有代码check in时单元测试都会被执行。如果单测对外部环境(网络、服务、中间件等)有依赖,容易导致持续集成机制的不可用。

正例:为了不受外界环境影响,要求设计代码时就把SUT的依赖改成注入,在测试时用spring 这样的DI框架注入一个本地(内存)实现或者Mock实现。

【推荐】编写单元测试代码遵守BCDE原则,以保证被测试模块的交付质量。

C:Correct,正确的输入,并得到预期的结果。

D:Design,与设计文档相结合,来编写单元测试。

E:Error,强制错误信息输入(如:非法数据、异常流程、业务允许外等),并得到预期的结果。

Mock可以用来解除外部服务依赖,从而保证了测试用例的独立性。

现在的互联网软件系统,通常采用了分布式部署的微服务,为了单元测试某一服务而准备其它服务,存在极大的依耐性和不可行性。

Mock可以减少全链路测试数据准备,从而提高了编写测试用例的速度。

传统的集成测试,需要准备全链路的测试数据,可能某些环节并不是你所熟悉的。最后,耗费了大量的时间和经历,并不一定得到你想要的结果。现在的单元测试,只需要模拟上游的输入数据,并验证给下游的输出数据,编写测试用例并进行测试的速度可以提高很多倍。

Mock可以模拟一些非正常的流程,从而保证了测试用例的代码覆盖率。

根据单元测试的BCDE原则,需要进行边界值测试(Border)和强制错误信息输入(Error),这样有助于覆盖整个代码逻辑。在实际系统中,很难去构造这些边界值,也能难去触发这些错误信息。而Mock从根本上解决了这个问题:想要什么样的边界值,只需要进行Mock;想要什么样的错误信息,也只需要进行Mock。

Mock可以不用加载项目环境配置,从而保证了测试用例的执行速度。

在进行集成测试时,我们需要加载项目的所有环境配置,启动项目依赖的所有服务接口。往往执行一个测试用例,需要几分钟乃至几十分钟。采用Mock实现的测试用例,不用加载项目环境配置,也不依赖其它服务接口,执行速度往往在几秒之内,大大地提高了单元测试的执行速度。

在实际工作中,不少同学用集成测试代替了单元测试,或者认为集成测试就是单元测试。这里,总结为了单元测试与集成测试的区别:

测试对象不同单元测试对象是实现了具体功能的程序单元,集成测试对象是概要设计规划中的模块及模块间的组合。

测试方法不同单元测试中的主要方法是基于代码的白盒测试,集成测试中主要使用基于功能的黑盒测试。

测试内容不同单元测试主要是模块内程序的逻辑、功能、参数传递、变量引用、出错处理及需求和设计中具体要求方面的测试;而集成测试主要验证各个接口、接口之间的数据传递关系,及模块组合后能否达到预期效果。

关注阿里云公众号或下载阿里云APP,关注云资讯,随时随地运维管控云服务

THE END
0.Java之构造器和构造方法的使用和意义时使用构造方法注意:例2和例3中this或super调用构造方法只能出现在构造方法中,而且必须出现在第一行,所以一个构造方法中第一行只能为this或super调用构造方法,两者不能同时调用构造方法出现,而且注意this或super调用构造方法时,要留构造方法出口,意思就是最后调用的构造方法中没有再调用别的构造方法! jvzquC41dnuh0lxfp0tfv8Vkw|nppp|gkykj1jwvkerf1mjvckrt1@=;87=9:
1.Java中的构造方法(构造函数)与普通方法区别及说明java这篇文章主要介绍了Java中的构造方法(构造函数)与普通方法区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教+ 目录 一、明白什么是构造方法,什么是普通方法? 所谓的构造方法,是一种特殊的方法,其作用是用来创建对象时初始化对象,即为对象成员变量赋初始值,总是与new运算jvzquC41yy}/lk:30pku1ywqitgn1<6:697cpl3jvo
2.Java类的构造方法(非常详细)Java 类中有一种非常特殊的方法,它会在创建对象时自动被调用,通常用于对象的初始化工作,它就是构造方法。 定义一个构造方法的语法如下: 访问修饰符 方法名(参数列表) { 方法体 } 首先是访问修饰符(非必需的)。然后是方法名和参数列表,其中方法名必须与类名相同,如果要定义无参的构造方法则直接使用()即可。最jvzquC41e0hjcwhjgpm/pny1xkkx1wqvsum10qyon
3.类和对象Home 面向对象的概念 类 实例 构造方法的重载 类和对象 面向对象的概念 面向对象就是:把数据及对数据的操作方法放在一起,作为一个相互依存的整体——对象。对同类对象抽象出其共性,形成类。类中的大多数数据,只能用本类的方法进行处理。类通过一个简单的外部接口与外界发生关系,对象与对象之间通过消息进行通信。jvzquC41ygh/u~ic0gjv0ls1jgpvp8hjcrzft:61r{ziqwd33a7/j}rn
4.Java中的构造方法Java 中的构造方法 一、什么是构造方法 构造方法(Constructor)是与类同名、没有返回值类型(连void都没有)的特殊方法,用于在创建对象时对对象进行初始化。换句话说,当你用new关键字来实例化一个类时,构造方法会被自动调用,从而完成初始化的操作。 简单示例:jvzquC41dnuh0lxfp0tfv8vsa6:27=>371gsvrhng1jfvjnnu1757A>74:8
5.Java:构造方法详解构造方法(Constructor)是 Java 类中用于初始化对象的特殊方法。以下是构造方法的全面解析: 一、基本概念 1. 构造方法的特点 方法名必须与类名完全相同 没有返回类型(连void都不写) 不能被static、final、abstract等修饰符修饰 在创建对象时自动调用(通过new关键字触发) jvzquC41dnuh0lxfp0tfv8vsa5?5895791gsvrhng1jfvjnnu1758>5856>
6.智能语音交互在线语音合成接口智能语音交互API文档必须订购在线语音合成服务,才能调用该接口。 该接口同步返回结果,等待引擎结果最长超时时间为1分钟。即该接口最长1分钟会返回结果。 每次合成的文本字符数最大为300字符;1个中文、1个英文、1个标点符号各算1个字符。 二. URI URI构造方法如下 请求方法 URI POST https://api-wuxi-1.cmecloud.cn:8443/api/lijvzquC41gerpwm3322>70ls1qr3iguu/egtug{4fqe5bt}neng548B<6
7.活动预告CCFCAD&CG专委会走进企业活动第7期题目:不规则参数域上光滑曲面的构造方法 嘉宾简介:博士,教授,博导。2008年在浙江大学获应用数学博士学位。主要研究领域为计算机辅助几何设计与图形学,主要研究方向为细分造型方法、曲线曲面插值与逼近、广义重心坐标、复杂参数域上曲面曲体的构造等。在ACM TOG、Computer Graphics Forum、Computer-Aided Design、Computer Aijvzq<84ve0idh7tti0io1}hecf5if‚l14283/95;30yivvq
8.中国古建筑的构造特点、损毁规律及保护修缮方法(下)02 中国古建筑的保护修缮方法 在对中国古建筑的构造特点、损毁规律有了初步认识之后,再来探讨对它的保护修缮方法就比较容易了。 中国古建筑的保护修缮,概括起来有五种情况 。jvzq<84yyy4tcw~cowyfwv3eqo5b1<4424902?5314=:87mvon
9.lazy<t>提供了6个构造方法,它的文档已经写得很清楚有关使用相同构造函数演示异常缓存的示例,请参阅Lazy<T>(Func<T>)构造函数。 该示例定义一个LargeObject类,该类将由多个线程之一延迟初始化。 代码的四个关键部分说明了如何创建初始值设定项、工厂方法、实际初始化和LargeObject类的构造函数,该类在创建对象时显示消息。 在Main方法的开头,该示例为LargeObject创建线jvzquC41oujo0vnetqyph}3eqo5{j6hp1noctjw{1fj76;83:*|>x|3332//c|uz
10.java构造方法(基础)有点儿意思java 构造方法(基础) java构造方法(基础) 构造方法也叫构造器,是创建对象时执行的特殊方法,一般用于初始化新对象的属性。它是专门用来创建对象的方法,当我们通过关键字new来创建对象时,其实就是在调用构造方法。 格式 public 类名称 (参数类型 参数名称){jvzquC41yy}/ewgnqiy/exr1mwgoi|zp34;0r8673698:;3jvor
11.Java构造方法的使用详解java构造方法是类的一种特殊方法,用来初始化类的一个新的对象,在创建对象(new 运算符)之后自动调用。Java 中的每个类都有一个默认的构造方法,并且可以有一个以上的构造方法+ 目录1. 看一个需求看一个需求:前面我们在创建人类的对象时,是先把一个对象创建好后,再给他的年龄和姓名属性赋值,如果现在要求,在创建人jvzquC41yy}/lk:30pku1jwvkerf1;795;;/j}r
12.java构造方法怎么生成java教程Java 提供了四种生成构造方法的方法:1. 无参构造方法,由编译器自动生成,不接受参数,将属性初始化为默认值;2. 有参构造方法,接受参数并根据参数初始化属性;3. 构造方法重载,提供具有不同参数列表的多个构造方法;4. 显式调用构造方法,使用 this() 语句调用其他构造方法。 jvzquC41yy}/rqu0ep5gcz4:667557mvon
13.构造方法与实例方法学Java的`Bei构造方法(Constructor)是一种特殊类型的方法,用于在创建对象时初始化对象的状态。 在Java内,构造方法名称与类名相同,且没有返回类型(甚至void)。因为构造方法的目的是初始化对象,而不是返回任何值。 为什么构造方法的目的是为了初始化对象:因为在创建对象时,通常需要一个初始化操作来保证对象有适合工作的状态,可以保证jvzquC41yy}/ewgnqiy/exr1ycxnPnxv/nrc1y43:2?15<6
14.详解Java中的有参构造方法与无参构造方法java这篇文章主要详细介绍了Java中有参构造方法与无参构造方法,文中有详细的代码示例,让大家清晰明了的了解到有参构造方法与无参构造方法、以及应用,需要的朋友可以参考下+ 目录 前言 遇到了就简单写一下吧,如果能够对你有帮助,点个赞吧。首先清晰明了的了解到有参构造方法与无参构造方法、以及应用,然后实战项目一般jvzquC41yy}/lk:30pku1ywqitgn1;=98;7gpl3jvo