大多数单元测试都集中于测试对象的行为以证明其有效。 这可以通过编写一个JUnit测试来实现,该测试调用对象的公共方法,然后测试这些调用的返回值是否与先前定义的一组期望值匹配。 这是一种非常常见且成功的技术。 但是,不应忘记对象也显示状态。 由于它是隐藏的,因此经常被忽略。

我于1995年夏季首次阅读Grady Booch的1994年的《 面向对象的分析和设计 》一书,它通过以下方式定义了对象的状态:

对象的状态包含对象的所有(通常是静态)属性以及这些属性中每个属性的当前(通常是动态)值。

他使用自动售货机示例定义了静态和动态状态之间的差异。 静态状态是通过机器始终准备好取钱的方式表现出来的,而动态状态是在任何给定实例中获得多少钱的状态。

我怀疑在这一点上,您会正确地辩称,显式行为测试确实会测试对象的状态,这是因为给定的方法调用返回了正确的结果,并且为了获得正确的结果,对象的状态也必须是是的...我会同意的。 但是,在极少数情况下,经典行为测试不适用。 当公共方法调用没有输出并且对对象不执行任何操作(更改其状态)时,会发生这种情况。 一个示例是返回void的方法或构造函数。 例如,给定一个具有以下签名的方法:

public void init();

…您如何确保已完成工作? 事实证明,有几种方法可以用来实现这一目标……

  • 在您的类中添加许多getter方法。 这并不是一个特别好的主意,因为您只是在松开后门的封装。
  • 放松封装:将私有实例变量打包为私有。 一个非常有争议的事情。 您可能会务实地认为,经过良好测试,正确和可靠的代码可能比具有高度的封装更好,但是我在这里不太确定。 这可能是一个短期修复,但将来可能会导致各种问题,因此应该有一种编写经过良好测试,正确和可靠的代码的方式,其中不包括破坏对象的封装
  • 编写一些使用反射来访问对象内部状态的代码。 这是迄今为止最好的主意。 不利的一面是,这需要付出相当大的努力,并且需要一定数量的编程能力。
  • 使用PowerMock的Whitebox测试课程为您完成艰苦的工作。

以下完全人为设计的方案演示了PowerMock的Whitebox类的用法。 它需要一个非常简单的AnchorTag <a>类,该类将在测试输入URL字符串有效之后构建一个锚标记。

public class AnchorTag {private static final Logger logger = LoggerFactory.getLogger(AnchorTag.class);/** Use the regex to figure out if the argument is a URL */private final Pattern pattern = Pattern.compile("^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}$");/*** A public method that uses the private method*/public String getTag(String url, String description) {validate(url, description);String anchor = createNewTag(url, description);logger.info("This is the new tag: " + anchor);return "The tag is okay";}/*** A private method that's used internally, but is complex enough to require testing in its own right*/private void validate(String url, String description) {Matcher m = pattern.matcher(url);if (!m.matches()) {throw new IllegalArgumentException();}}private String createNewTag(String url, String description) {return "<a href=\"" + url + "\">" + description + "</a>";}
}

URL验证测试是使用正则表达式和Java Pattern对象完成的。 使用Whitebox类将确保正确配置模式对象,并且我们的AnchorTag处于正确的状态。 下面的JUnit测试证明了这一点:

/*** Works for private instance vars. Does not work for static vars.*/@Testpublic void accessPrivateInstanceVarTest() throws Exception {Pattern result = Whitebox.<pattern> getInternalState(instance, "pattern");logger.info("Broke encapsulation to get hold of state: " + result.pattern());assertEquals("^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}$", result.pattern());}

该测试的关键是:

Pattern result = Whitebox.<pattern> getInternalState(instance, "pattern");

…使用反射返回Pattern对象的私有实例变量。 一旦可以访问该对象,我们只需调用它即可询问它是否已正确初始化:

assertEquals("^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}$", result.pattern());

总而言之,我建议仅在无法使用简单直接的经典JUnit测试进行行为测试时,才应使用PowerMock显式测试对象的内部状态。 话虽如此,它是工具箱中的另一个工具,可以帮助您编写更好的代码。

参考:来自JCG合作伙伴的 PowerMock测试对象的内部状态 调试队长博客上的 Roger。

相关文章 :
  • JUnit 4.9(测试版3)中的规则
  • Servlet 3.0异步处理可将服务器吞吐量提高十倍
  • 用Scala测试
  • Java工具:源代码优化和分析
  • Java教程和Android教程列表

翻译自: https://www.javacodegeeks.com/2011/10/testing-objects-internal-state-with.html

使用PowerMock测试对象的内部状态相关推荐

  1. powermock模拟对象_使用PowerMock测试对象的内部状态

    powermock模拟对象 大多数单元测试都集中于测试对象的行为以证明其有效. 这可以通过编写一个JUnit测试来实现,该测试调用对象的公共方法,然后测试这些调用的返回值是否与先前定义的一组期望值匹配 ...

  2. 【设计模式】享元模式 简介 ( 定义 | 对象池 | 内部状态 | 外部状态 | 适用场景 | 相关角色 )

    文章目录 I . 享元模式 简介 II . 享元模式 内部状态 和 外部状态 III . 享元模式 适用场景 IV . 享元模式 优缺点 V . 享元模式 相关模式 VI . 享元模式 相关角色 I ...

  3. 处理对象的多种状态及其相互转换——状态模式

    本文转载自 :http://blog.csdn.net/lovelion/article/details/8522982 "人有悲欢离合,月有阴晴圆缺",包括人在内,很多事物都具有 ...

  4. 软件测试基础 按照测试对象划分 界面测试(UI测试.响应式页面 可靠性测试 容错性测试 文档测试 平台测试 易用性测试等

    软件测试进阶 1.APP 的测试 2. 按照测试对象划分 2.1界面测试(UI测试) 3.响应式页面 4.可靠性测试 5.容错性测试 6.文档测试 7.平台测试: 7.1 PC: 7.2.手机端: 8 ...

  5. NVME CLI -- nvme 命令查看NVME设备内部状态

    文章目录 NVME 和 AHCI 性能比较 NVME-CLI nvme工具使用 1. 安装 2. 命令综述 3. 基本命令演示 4. NVME 固件设备升级 近期在做一些rocksdb on 新硬件的 ...

  6. Hibernate持久化对象三种状态

    持久化类类三种状态介绍 瞬时态:也叫做临时态或自由态,它一般指我们new出来的对象,它不存在OID,与hibernate session无关联,在数据库中也无记录.它使用完成后,会被jvm直接回收掉, ...

  7. powermock模拟对象_使用PowerMock模拟构造函数

    powermock模拟对象 在我看来,依赖注入的主要好处之一是可以将模拟和/或存根对象注入代码中,以提高可测试性,增加测试覆盖率并编写更好,更有意义的测试. 但是,有时候您会遇到一些不使用依赖注入的传 ...

  8. AGS 对象池和状态概要

    AGS是ArcGIS Server的简称,AGS开发首先要理解对象池和状态(object pooling and gis server state),ags帮助文档对此有很详细的描述,想在短时间内看完 ...

  9. 对象的当前状态使该操作无效 说明: 执行当前 Web 请求期间,出现未处理的异常。...

    这个异常在页面数据量小的时候并不会触发,只在页面数据量大的情况下才会出现, 异常信息如下: 对象的当前状态使该操作无效.  说明: 执行当前 Web 请求期间,出现未处理的异常.请检查堆栈跟踪信息,以 ...

最新文章

  1. HDU - 5788 Level Up(主席树+dfs序+树状数组)
  2. 再见Spring Security!推荐一款功能强大的权限认证框架,用起来够优雅!
  3. java 自动化测试报告_Java自动化测试框架-10 - TestNG之测试结果篇
  4. python里order_volume_Python 基础知识:Method Resolution Order (MRO) 和 super
  5. jquery显示隐藏切换_jQuery显示,隐藏,切换
  6. [20170925]什么是FQDN(关于hostname).txt
  7. 简单的Latex模板
  8. 一二线城市都有哪些互联网公司是大家都想去的?
  9. 一些常用软件的网络端口协议分类介绍
  10. 软考-软件工程师常用公式及知识点
  11. 设计在链式存储结构上交换二叉树中所有结点左右子树的算法
  12. matlab函数power,Matlab中Powergui介绍.pdf
  13. tippy.js悬浮提示工具插件
  14. Windows10黑体字体
  15. RecyclerView滑动置顶点击置顶的实现
  16. 数据挖掘ID3算法详解
  17. 使用matplotlib绘制折线图(绘制一天当中的气温变化)
  18. win10提示bitlocker加密的硬盘需要格式化
  19. 全球与中国5G用聚酰亚胺薄膜市场深度研究分析报告
  20. 【做题笔记】P2327 [SCOI2005]扫雷

热门文章

  1. mybatis多表新增如何获取主键ID
  2. 如何实现下拉框的绑定
  3. spring注入私有字段_Spring字段依赖注入示例
  4. 结果集 tostring_关于避免对toString()结果进行解析或基于逻辑的美德
  5. python kotlin_Java和Python中类似Kotlin的生成器,续:附加参数
  6. javaone_JavaOne 2015 –第二十版十大收获
  7. JavaFX的科幻用户界面第1部分
  8. 借助Fargate和EKS,AWS甚至可以实现Cloud-ier和Kuberneties-ier
  9. jsf tree组件_JSF:在传统组件和时尚性能杀手之间进行选择
  10. threadlocals_如何使用ThreadLocals射击自己