在JUnit测试中使用Builder模式
这并不是要成为技术含量很高的职位。 这篇文章的目的是为您提供一些指导,以使您的JUnit测试生活更加轻松,使您能够在几分钟内编写复杂的测试场景,并具有易于阅读的测试优势。
单元测试中有两个主要部分,需要编写许多引导程序代码:
- 设置部分:构建初始状态需要构建将被馈送到SUT(被测系统)的初始对象
- 断言部分:构造输出对象的所需图像,并仅对所需数据进行断言。
为了降低构建用于测试的对象的复杂性,我建议在以下解释中使用Builder模式:
这是域对象:
public class Employee {private int id;private String name;private Department department;//setters, getters, hashCode, equals, toString methods
此域对象的生成器如下所示:
public class EmployeeBuilder {private Employee employee;public EmployeeBuilder() {employee = new Employee();}public static EmployeeBuilder defaultValues() {return new EmployeeBuilder();}public static EmployeeBuilder clone(Employee toClone) {EmployeeBuilder builder = defaultValues();builder.setId(toClone.getId());builder.setName(toClone.getName());builder.setDepartment(toClone.getDepartment());return builder;}public static EmployeeBuilder random() {EmployeeBuilder builder = defaultValues();builder.setId(getRandomInteger(0, 1000));builder.setName(getRandomString(20));builder.setDepartment(Department.values()[getRandomInteger(0, Department.values().length - 1)]);return builder;}public EmployeeBuilder setId(int id) {employee.setId(id);return this;}public EmployeeBuilder setName(String name) {employee.setName(name);return this;}public EmployeeBuilder setDepartment(Department dept) {employee.setDepartment(dept);return this;}public Employee build() {return employee;}
}
如您所见,我们有一些工厂方法:
public static EmployeeBuilder defaultValues()public static EmployeeBuilder clone(Employee toClone)public static EmployeeBuilder random()
这些方法返回不同的构建器:
- defaultValues:每个字段的一些硬编码值(或Java默认值-当前实现)
- clone:将获取初始对象中的所有值,并使您可以更改其中一些值
- random:将为每个字段生成随机值。 当您有很多字段在测试中不需要时非常有用,但是您需要将它们初始化。 getRandom *方法是在另一个类中静态定义的。
您可以添加其他方法来根据需要初始化构建器。
此外,构建器还可以处理一些不那么容易构建和更改的对象。 例如,让我们稍微更改Employee对象,使其不可变:
public class Employee {private final int id;private final String name;private final Department department;...
}
现在,我们失去了按需更改字段的可能性。 但是使用以下形式的构建器,我们可以在构造对象时重新获得这种可能性:
public class ImmutableEmployeeBuilder {private int id;private String name;private Department department;public ImmutableEmployeeBuilder() {}public static ImmutableEmployeeBuilder defaultValues() {return new ImmutableEmployeeBuilder();}public static ImmutableEmployeeBuilder clone(Employee toClone) {ImmutableEmployeeBuilder builder = defaultValues();builder.setId(toClone.getId());builder.setName(toClone.getName());builder.setDepartment(toClone.getDepartment());return builder;}public static ImmutableEmployeeBuilder random() {ImmutableEmployeeBuilder builder = defaultValues();builder.setId(getRandomInteger(0, 1000));builder.setName(getRandomString(20));builder.setDepartment(Department.values()[getRandomInteger(0, Department.values().length - 1)]);return builder;}public ImmutableEmployeeBuilder setId(int id) {this.id = id;return this;}public ImmutableEmployeeBuilder setName(String name) {this.name = name;return this;}public ImmutableEmployeeBuilder setDepartment(Department dept) {this.department = dept;return this;}public ImmutableEmployee build() {return new ImmutableEmployee(id, name, department);}
}
当我们难以构造对象或需要更改最终字段时,这非常有用。
这是它的最终结果:
没有建设者:
@Testpublic void changeRoleTestWithoutBuilders() {// building the initial stateEmployee employee = new Employee();employee.setId(1);employee.setDepartment(Department.DEVELOPEMENT);employee.setName("John Johnny");// testing the SUTEmployeeManager employeeManager = new EmployeeManager();employeeManager.changeRole(employee, Department.MANAGEMENT);// building the expectationsEmployee expectedEmployee = new Employee();expectedEmployee.setId(employee.getId());expectedEmployee.setDepartment(Department.MANAGEMENT);expectedEmployee.setName(employee.getName());// assertionsassertThat(employee, is(expectedEmployee));}
与建设者:
@Testpublic void changeRoleTestWithBuilders() {// building the initial stateEmployee employee = EmployeeBuilder.defaultValues().setId(1).setName("John Johnny").setDepartment(Department.DEVELOPEMENT).build();// building the expectationsEmployee expectedEmployee = EmployeeBuilder.clone(employee).setDepartment(Department.MANAGEMENT).build();// testing the SUTEmployeeManager employeeManager = new EmployeeManager();employeeManager.changeRole(employee, Department.MANAGEMENT);// assertionsassertThat(employee, is(expectedEmployee));}
如您所见,测试的大小要小得多,对象的构造也变得更加简单(如果代码格式更好,也会更好)。 如果您具有更复杂的域对象(在实际应用程序中,尤其是在遗留代码中),则差异更大。
玩得开心!
参考:来自Java出现日历博客的JCG合作伙伴 Stefan Bulzan 在JUnit测试中使用了Builder模式 。
翻译自: https://www.javacodegeeks.com/2012/12/using-builder-pattern-in-junit-tests.html
在JUnit测试中使用Builder模式相关推荐
- idea使用junit测试_在JUnit测试中使用Builder模式
idea使用junit测试 这并不是要成为技术含量很高的职位. 这篇文章的目的是为您提供一些指导,以使您的JUnit测试生活更加轻松,使您能够在几分钟内编写复杂的测试场景,并获得具有高度可读性的测试. ...
- 浅谈Junit测试中反射和Jmock的应用
最近由于项目的需要,开发后的代码强制编写Junit测试,并且达到一定的coverage probility(主要应付客户).所以,为了达到一定的覆盖率,鄙人不得不在Case中大量使用反射(一般是针对p ...
- java如何保存初始化数据_java – 如何在JUnit测试中初始化数据
我的任务是为服务层编写压力(负载)测试.主要是CRUD操作.我们使用JUnit作为测试框架,使用JUnitPerf构建负载测试,使用 Spring注入服务bean,使用hibernate访问数据库. ...
- Junit测试中找不到junit.framework.testcase
在使用Junit进行测试时,出现如下问题: 找不到junit.framework.testcase 解决方法: 选中项目->属性->Java构建路径->库->添加外部jar 在 ...
- Eclipse中Junit测试中@Before不执行
场景 在使用Junit进行单元测试时,一部分获取JPA的entityManager的代码将其放在了 @Before标注的方法中,这样每次执行@TEST标注的方法时会首先执行@Before标注的方法. ...
- android builder模式 插件,如何在Kotlin中实现Builder模式?
首先,在大多数情况下,您不需要在Kotlin中使用构建器,因为我们有默认和命名参数 . 这使您可以写 class Car(val model: String? = null, val year: In ...
- java中的builder模式
import android.text.TextUtils;/*** Created by toothwind on 2017/7/19.* you can contact me at : tooth ...
- springmvc通过@Value注解读取Properties配置文件的值,junit测试可以取到值,但是在业务中无法读取
最近试着做了个springmvc 项目,在加入 发邮件 功能时遇到的问题. Spring 通过注解获取*.porperties文件的内容,除了xml配置外,还可以通过@value方式来获取. @val ...
- 设计模式学习笔记——建造者(Builder)模式
设计模式学习笔记--建造者(Builder)模式 @(设计模式)[设计模式, 建造者模式, builder] 设计模式学习笔记建造者Builder模式 基本介绍 建造者案例 类图 实现代码 Build ...
最新文章
- java包装_Java基础之神奇的包装类(一)
- 背水一战 Windows 10 (65) - 控件(WebView): 对 WebView 中的内容截图, 通过 Share Contract 分享 WebView 中的被选中的内容...
- (转)Windows7 “上帝模式”的原理
- spark 资源参数调优
- 【回文自动机】bzoj3676 [Apio2014]回文串
- Github中Tag的使用
- 计算机图形学Web前端笔记-浏览器中心点转场景坐标理论及实现(two.js)
- Android中XML数据解析
- 面试被问项目上线没_面试官的最爱问“分布式”核心设计问题,没掌握的不妨来看看...
- MFC中显示一张位图
- android webview 百度地图,Android WebView显示地图
- RouterOS 动态IP接入上网设置教程(超详细)
- 阿帕虎题库管理系统服务器,阿帕虎题库管理系统
- 航天金税开票导入导出txt格式
- 计算器算贝塞尔公式_我不是灯光设计师,但是我会算空间的平均照度
- ACCESS入门教程(五)数据的类型和属性
- django学习日志(模板的渲染过程)第八部分:字符串数据转义
- WPF 加载PDF文件
- python打开sql,Python打开Microsoft SQL Server MDF文件
- 数据分析学习笔记(二)数据分析三思维七技巧
热门文章
- linux-basic(12)正则表达式与文件格式化处理
- 高特权级代码段转向低特权级代码段(利用 ret(retf) 指令实现 jmp from ring0 to ring3)
- ubuntu系统下安装docker并部署Springboot+mysql+redis
- 双列集合Map的实现类
- 分解因数 递归_递归分解WAR文件
- groovy lambda_Java Lambda流和Groovy Clouse的比较
- php cdi_本机CDI限定词:@Any和@Default
- 设计模式适配器模式_21世纪的设计模式:适配器模式
- java多线程 异常处理_Java8多线程ForkJoinPool:处理异常
- java 从未导入_Java 8的10个您从未听说过的功能