(单元测试)JavaBeans的技巧

如果您正在编写Java代码,那么您至少要编写一些遵循JavaBean约定的类,即,具有带有公共getter和setter方法的私有属性的类,包含无参数的构造函数,可序列化,并且遵守Equals和HashCode合同。 最重要的是,您可能还会抛出一个有用的toString()实现。

例如,如果我们使用一个非常简单的类MyBean来包含两个名为id和name的字段,那么我们将得到以下代码:

MyBean – JavaBean示例

package it.jdev.example;import java.io.Serializable;public class MyBean implements Serializable {private static final long serialVersionUID = 6170536066049208199L;private long id;private String name;public MyBean() {super();}public long getId() {return id;}public void setId(final long id) {this.id = id;}public String getName() {return name;}public void setName(final String name) {this.name = name;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + (int) (id ^ (id >>> 32));result = prime * result + ((name == null) ? 0 : name.hashCode());return result;}@Overridepublic boolean equals(final Object obj) {if (this == obj) {return true;}if (obj == null) {return false;}if (getClass() != obj.getClass()) {return false;}final MyBean other = (MyBean) obj;if (id != other.id) {return false;}if (name == null) {if (other.name != null) {return false;}} else if (!name.equals(other.name)) {return false;}return true;}@Overridepublic String toString() {return "MyBean [id=" + id + ", name=" + name + "]";}}

因此,对于只有两个字段的类,我们最终获得了70行代码。 那是很多样板代码。 而且,每次添加或更改任何属性时,都必须调整或重新生成许多样板代码。

Lombok项目进行救援

幸运的是,有一个很好的开源工具,旨在减少我们在MyBean类中处理的样板代码的类型。 它被称为Lombok计划 。 只需将Lombok作为插件安装在您最喜欢的IDE中,然后将Lombok jar文件包含在构建类路径中,或将其添加为maven依赖项,就可以了。

Lombok项目包含很多不同的注释,但是对于我们的示例,我们只需要一个注释:@Data。 当我们将注释应用于代码时,我们从最初的70行减少到仅15行代码,而Lombok项目将在编译过程中为我们生成所有方法。 而且,我们再也不必担心我们的hashCode(),equals()和toString()方法运行不同步。

MyBean –我们的带有Project Lombok的JavaBean示例

package it.jdev.example;import java.io.Serializable;import lombok.Data;@Data
public class MyBean implements Serializable {private static final long serialVersionUID = 6170536066049208199L;private long id;private String name;}

救命,我的代码覆盖率下降了

现在,我们有了Lombok项目为我们生成了样板代码,这一事实并不一定意味着我们可以跳过对生成的方法进行单元测试。 尤其是如果您重视代码覆盖率,并且在CI设置中仅进行了最小限度的覆盖率检查,则需要添加一些额外的测试。 幸运的是,有一些简单的方法可以提高代码覆盖率。

测试可串行性

如果您的可序列化对象包含任何自定义字段,则这些字段也应该可序列化。 但是,这很容易被忽略。 使用Apache Commons Lang库中的SerializationUtils类,您可以编写一个非常简单的测试,检查对象是否正确序列化,然后再次反序列化。

测试我们的MyBean的可序列化性

package it.jdev.example;import static org.junit.Assert.*;import org.apache.commons.lang3.SerializationUtils;
import org.junit.Before;
import org.junit.Test;public class MyBeanTest {private MyBean myBean;@Beforepublic void setUp() throws Exception {myBean = new MyBean();myBean.setId(123L);myBean.setName("Bean, James Bean");}@Testpublic void beanIsSerializable() {final byte[] serializedMyBean = SerializationUtils.serialize(myBean);final MyBean deserializedMyBean = (MyBean) SerializationUtils.deserialize(serializedMyBean);assertEquals(myBean, deserializedMyBean);}}

测试getter和setter方法

测试JavaBean的getter和setter方法对可能很快变得非常乏味。 幸运的是,有一个很好的测试库叫做meanBean ,可以为我们完成工作。 因此,在将以下方法添加到我们的单元测试中之后,我们就完成了对吸气剂和吸气剂的测试:

测试我们的MyBean示例的获取器和设置器

@Test
public void getterAndSetterCorrectness() throws Exception {new BeanTester().testBean(MyBean.class);
}

测试equals()和hashCode()

自己测试equals和hashCode契约的所有复杂性是一项非常麻烦的任务。 同样,有一些不错的工具可以帮助您轻松实现。 前述的meanBean库提供了这样做的功能。 但是,我发现像EqualsVerifier这样的工具在其测试中要更严格一些,并且还提供有关任何错误的详细说明。 因此,我们将在我们的套件中添加下一个测试用例:

测试我们的MyBean示例的Equals和HashCode契约

@Test
public void equalsAndHashCodeContract() throws Exception {EqualsVerifier.forClass(MyBean.class).suppress(Warning.STRICT_INHERITANCE, Warning.NONFINAL_FIELDS).verify();
}

请注意,我们在此处禁止显示某些警告。 有关原因的更多信息,请参见有关错误消息的EqualsVerifier信息: http ://www.jqno.nl/equalsverifier/errormessages/。

JavaBean测试用例的通用基类

即使借助meanBean和EqualsVerifier之类的工具来完成繁重的工作,您也不想一遍又一遍地重复相同的测试代码。 因此,您可能希望将测试放在抽象的基类中。 该基类的可能实现可能类似于以下内容:

用于测试JavaBeans的抽象基类

package it.jdev.example;import static org.junit.Assert.assertEquals;
import java.io.Serializable;
import java.time.LocalDateTime;
import nl.jqno.equalsverifier.EqualsVerifier;
import nl.jqno.equalsverifier.Warning;
import org.apache.commons.lang3.SerializationUtils;
import org.junit.Test;
import org.meanbean.lang.Factory;
import org.meanbean.test.BeanTester;public abstract class AbstractJavaBeanTest {protected String[] propertiesToBeIgnored;@Testpublic void beanIsSerializable() throws Exception {final T myBean = getBeanInstance();final byte[] serializedMyBean = SerializationUtils.serialize((Serializable) myBean);@SuppressWarnings("unchecked")final T deserializedMyBean = (T) SerializationUtils.deserialize(serializedMyBean);assertEquals(myBean, deserializedMyBean);}@Testpublic void equalsAndHashCodeContract() {EqualsVerifier.forClass(getBeanInstance().getClass()).suppress(Warning.STRICT_INHERITANCE, Warning.NONFINAL_FIELDS).verify();}@Testpublic void getterAndSetterCorrectness() throws Exception {final BeanTester beanTester = new BeanTester();beanTester.getFactoryCollection().addFactory(LocalDateTime.class, new LocalDateTimeFactory());beanTester.testBean(getBeanInstance().getClass());}protected abstract T getBeanInstance();/*** Concrete Factory that creates a LocalDateTime.*/class LocalDateTimeFactory implements Factory {@Overridepublic LocalDateTime create() {return LocalDateTime.now();}}}

请注意,仅出于娱乐目的,我添加了LocalDateTimeFactory,以便meanBean可以测试您可能在JavaBean类中使用的任何LocalDateTime属性的获取器和设置器。

将抽象基类应用于MyBean示例的单元测试中,结果单元测试将类似于:

MyBean的最终单元测试

package it.jdev.example;import static org.junit.Assert.*;import org.junit.Test;public class MyBeanTest extends AbstractJavaBeanTest<MyBean> {@Overrideprotected MyBean getBeanInstance() {return new MyBean();}}

翻译自: https://www.javacodegeeks.com/2014/09/tips-for-unit-testing-javabeans.html

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

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

相关文章

js中的正则表达式

正则表达式等名称并不能让人一下就能明白是什么意思&#xff0c;我认为称之为 规则表达式 更为合理&#xff0c;就是描述一个字符串规则的表达式。 语法 正则表达式的语法有两种&#xff0c;下面第一种语法稍显 怪异&#xff0c;但确实是合法的并且相对方便&#xff0c;推荐。…

Hadoop namenode启动瓶颈分析

转载&#xff1a;http://blog.csdn.net/AE86_FC/archive/2010/08/26/5842020.aspx NameNode启动过程详细剖析 NameNode中几个关键的数据结构 FSImage Namenode会将HDFS的文件和目录元数据存储在一个叫fsimage的二进制文件中&#xff0c;每次保存fsimage之后到下次保存之间的所有…

Java 9 –终极功能列表

这篇文章将针对即将到来的Java 9版本进行更新&#xff0c;新增功能 &#xff08; 最新更新&#xff1a;2014年 9月9日 &#xff09; OpenJDK开发正在加快速度&#xff1a;2014年3月Java 8发布之后&#xff0c;我们预计将进入2年的发布周期。 据报道&#xff0c;Java 9将于2016…

2018.3.30 边框应用与导航栏设置

<!DOCTYPE html><html> <head> <meta charset"utf-8" /> <title></title> <style type"text/css"> /*制作三角形*/ #one{ width: 0px; …

centos 更改用户登录宿主机时间

chage -l username (查看用户登录时间&#xff1a;username为查看的用户) chage -M 90 username &#xff08;将用户登录主机的时间更改为90天&#xff09; 转载于:https://www.cnblogs.com/MUQINGFENG123/p/11075912.html

js中的作用域和作用域链

作用域就是变量与函数的可访问范围。在js中只有 全局作用域 和 函数作用域 &#xff0c;并没有块级作用域。 全局作用域 在所有函数外定义的变量、声明的函数就是全局作用域&#xff0c;在全部环境下都可以访问。 var a 111;function fn(){console.log(a); }fn(); // 打印了…

CryEngine3 引擎非商业用途将免费

CryEngine3引擎非商业用途将免费:8月发布 http://t.cn/hdEr45】Crytek日前宣布将在今年8月免费推出CryEngine3引擎的开发包&#xff0c;登录Crytek官网注册&#xff0c;签署保密协议保证不将CryEngine3用作商业用途&#xff0c;就可获得CryEngine3软件授权。Crytek官网上的一份…

vue打包后不使用服务器直接访问方法

根据官网打包执行npm run build 后dist文件夹打开的index.html 是空白 需要开启http服务器才能访问&#xff0c;以下是解决办法 1、找到config文件夹下的index文件 修改成 2、找到build文件夹下的until文件 修改成 然后执行npm run build重新打包下就ok了 更多专业前端知…

IntelliJ中的键盘快捷键

我上周参加了Hadi Hariri在JavaOne上的演讲。 他介绍了很多我不知道的IntelliJ键盘快捷键。 非常有用的谈话。 我在下面列出了一些最有用的。 Cmd-1&#xff1a;将焦点移到“项目”窗口 在此输入任何类名&#xff08;包括使用Camel Case&#xff0c;例如HW来查找HelloWorld&a…

OpenStack虚机网卡的创建过程

原文&#xff1a;https://www.sdnlab.com/20286.htmlOpenStack最基本和常用的操作就是启动虚机。虚机启动的过程中涉及很多内容&#xff0c;其中非常重要的一个环节就是创建并绑定虚机的虚拟网卡。虚机的创建和管理是Nova的任务&#xff0c;虚机网络的创建和管理是Neutron的任务…

js中的原型与原型链

js的学习有三座大山&#xff0c; 原型/原型链 、 作用域/闭包 、 异步/单线程&#xff0c;这三个知识点虽然基础但是入门时理解起来比较困难&#xff0c;本文先整理总结原型和原型链这一知识点。 1. 原型链怎么来的&#xff1f;对象的原型和function的prototype属性有什么关系…

线性表--算法设计题2.29

已知A&#xff0c;B和C为三个递增有序的线性表&#xff0c;现要求对A表作如下操作&#xff1a;删去那些既在B表中出现又在C表中出现的元素。试对顺序表编写实现上述操作的算法.&#xff08;注意&#xff1a;题中没有特别指明同一表中的元素值各不相同&#xff09;。C code: #in…

HTML5 audio 如何实现播放多个MP3音频

<audio>标签是HTML5中的新标签&#xff0c;定义声音用于嵌入音频内容&#xff0c;比如音乐或其他音频流。用的比较多音频格式是.mp3。 <audio>标签常用属性如下表 属性值描述autoplayautoplay添加该属性后&#xff0c;音频会自动播放controlscontrols设置后&…

Java代码中的典型错误

该页面包含在与我一起工作的人的Java代码中看到的最典型的错误。 静态分析&#xff08;出于明显的原因&#xff0c;我们使用查询无法捕获所有错误&#xff0c;这就是为什么我决定在此处列出所有错误的原因。 如果您要在此处添加其他内容&#xff0c;请告诉我&#xff0c;我们将…

windwos下ntp服务器配置 arm平台ntp客户端获取同步时间

项目需要使用同步时间&#xff0c;在arm-linux开发板上&#xff0c;移植了ntp客户端&#xff0c;查看了一些资料&#xff0c;最终发现使用windows自带的ntp服务器比较方便&#xff0c;而且很靠谱&#xff0c;使用配置了一番&#xff0c;已经能够正常使用 详细步骤&#xff1a; …

css 控制图片最大宽度

CSS 限制图片最大宽度 (本文来自本站原创&#xff0c;转载请务必注明出处&#xff01;)我们在制作一个网页的时候&#xff0c;经常要对一个区域里可能出现的图片的宽度进行限制&#xff0c;不然它可能会把页面撑得很烂很烂。如果你采用固定宽度&#xff0c;长度来设置的话&…

BOM(Browser Object Model)

BOM&#xff08;浏览器对象模型&#xff09;&#xff0c;提供了一系列操作浏览器&#xff0c;获取浏览器信息的接口。这些接口在平时的工作中会经常用到&#xff0c;例如当前页面的刷新&#xff0c;获取url的参数等等。 注&#xff1a;图片来自 http://www.dreamdu.com/javascr…

入门 IT 行业,该具备哪些技能?

对于刚开始进入IT的新人来说&#xff0c;“必备技能”往往意味着一个长长的、标有重要度的学习列表&#xff0c;但是过长的列表通常会导致新人不知如何开始学习&#xff0c;压力倍增。本文尝试列举出最重要的几个技能&#xff0c;也期望通过此列表能给新人一个比较明确的学习重…

实验七作业

Part 1:验证性实验 将line29&#xff1a;for(i0;i<N;i)改为while(!feof(fp)) // 从文本文件file1.dat中读取数据&#xff0c;找出最高分和最低分学生信息&#xff0c;并输出在屏幕上 #include <stdio.h> #include <stdlib.h>#define N 10// 定义一个结构体类型…

块级格式化上下文(Block Formatting Context)

CSS块级格式化上下文是块级盒子的一种能力&#xff0c;这种能力并不是直接通过css属性声明而获得的&#xff0c;而是添加css的一部分相关属性之后自动获得的能力&#xff0c;也就是说没有一个明确的属性就是生成块级格式化上下文的。 块级格式化上下文的能力就是让具有该能力的…