网管联盟 | 网管论坛 | 网管u家 | 网管博客 | 网管软件 | 网管求职 | 小游戏 | 网管搜索 | 网管原创 | 网管聚合 | 网管读摘 | 网管焦点 | 世界素材 | 会员投稿 | 会员中心 
中国网管联盟
Windows Linux Cisco 网络技术 数据库 黑客攻防 DotNet Java PHP 认证 新闻资讯 服务器 存储资讯 网络设备 网管学堂 技术专题 焦点 网吧频道
 当前位置: > bitsCN.com > JAVA > 开源技术 > JUnit > 关于Java单元测试中的伪对象介绍(图)  

关于Java单元测试中的伪对象介绍(图)

2005-10-28  作者:BitsCN整理  来源:中国网管联盟  点评 投稿 收藏


  在单元测试的策略中伪对象被广泛使用。他从测试中分离了外部的不需要的因素并且帮助开发人员专注于被测试的功能。
  
  EasyMock是一个在这方面很有名的工具,可以在运行时为给定的接口创建伪对象。伪对象的行为可以在测试用例中的执行测试代码之前被定义。EasyMock基于java.lang.reflect.Proxy,他可以根据给定的接口创建动态代理类或者对象。但因为使用Proxy使得他有一个天生的缺陷:只能创建基于接口的伪对象。
  
  Mocquer是一个类似的工具,但他扩展了EasyMock的功能能够支持创建类的伪对象。
  
  Mocquer介绍
  
  Mocquer基于Dunamis项目,被用来为特定的类或接口生成动态代理类或对象。为方便使用,他遵循EasyMock的类和方法的命名规范,只是在内部使用不同的实现方法。
  
  MockControl是Mocquer项目中最重要的类。他被用来控制伪对象的生命周期和行为定义。这个类中有四类方法。
  
  1、生命周期控制方法:
  
  ·public void replay();
  ·public void verify();
  ·public void reset();
  
  伪对象在他的生命周期中有三种状态:准备态、工作态、验证态。图1显示了伪对象的生命周期。 网管bitscn_com
   
  Figure 1. Mock object life cycle
  
  刚开始,伪对象处于准备态,他的表现行为可以在这里定义。replay()将改变伪对象的状态为工作态。在这个状态中所有伪对象的方法调用将会遵循在准备态下定义的行为。在verify()调用后,伪对象就处于验证态。MockControl会比较伪对象的预定义行为与实际行为是否匹配。匹配规则依赖于使用的MockControl类型,这个会在稍后解释。开发人员可以在需要时调用replay()来重现预定义的行为。而任何状态下调用reset()将会清除状态历史并重置为初始的准备态。
  
  2、工厂方法
  
  ·public static MockControl createNiceControl(...);
  ·public static MockControl createControl(...);
  ·public static MockControl createStrictControl(...);
  
  Mocquer提供了三种MockControl:宽松的,普通的和严格的。开发人员可以在自己的测试用例中根据测试的内容(测试点)和测试的执行方式(测试策略)选择相应的MockControl。宽松的MockControl是最随意的,他不关心伪对象中方法调用的顺序,甚至未预期的方法调用,只是返回一个缺省值(依赖于方法的返回值)。普通的MockControl比宽松的MockControl严格些,未预期的方法调用会导致AssertionFailedError异常。严格的MockControl是最严格的,如果伪对象在工作态下方法调用的顺序与准备态的不同,就会抛出AssertionFailedError异常。下表显示了三种不同MockControl的区别。
网管联盟bitsCN_com

  
  下面是每一个工厂方法的两个不同版本。
  public static MockControl createXXXControl(Class clazz); public static MockControl createXXXControl(Class clazz,  Class[] argTypes, Object[] args);
  
  如果类是作为接口来模拟的或者他有一个公共或保护的缺省构造函数,则第一个版本的方法会被使用。否则第二个版本会被用来定义标识和提供参数给期望的构造函数。
  
  例如,假设ClassWithNoDefaultConstructor是一个没有缺省构造函数的类:
  
  public class ClassWithNoDefaultConstructor {
  public ClassWithNoDefaultConstructor(int i) {
  ...
  }
  ...
  }
  
  ·伪对象获取方法
  
  public Object getMock();
  
  每一个MockControl包含一个生成的伪对象的引用。开发人员可以使用这个方法取得伪对象并且转换为实际的对象类型。
  
  //get mock control
  MockControl control = MockControl.createControl(Foo.class);
  //Get the mock object from mock control
  Foo foo = (Foo) control.getMock();

网管论坛bbs_bitsCN_com


  
  ·行为定义方法
  
  public void setReturnValue(... value);
  public void setThrowable(Throwable throwable);
  public void setVoidCallable();
  public void setDefaultReturnValue(... value);
  public void setDefaultThrowable(Throwable throwable);
  public void setDefaultVoidCallable();
  public void setMatcher(ArgumentsMatcher matcher);
  public void setDefaultMatcher(ArgumentsMatcher matcher);
  
  MockControl允许开发人员定义伪对象的每一个方法的行为。当他在准备态时,开发人员可以调用伪对象的方法。首先规定哪一个调用方法的行为需要被定义。然后开发人员可以使用行为定义的方法之一来定义行为。例如,看一下下面的Foo类:
  //Foo.java
  public class Foo {
  public void dummy() throw ParseException {
  ...
  }   public String bar(int i) {
  ...
  }   public boolean isSame(String[] strs) {
  ...
  }   public void add(StringBuffer sb, String s) {
  ...
  }
  }
  
  伪对象的行为可以按照下面的方式来定义: 网管u家u.bitsCN.com
  
  //get mock control
  MockControl control = MockControl.createControl(Foo.class);
  //get mock object
  Foo foo = (Foo)control.getMock();
  //begin behavior definition
  //specify which method invocation's behavior
  //to be defined.
  foo.bar(10);
  //define the behavior -- return "ok" when the
  //argument is 10
  control.setReturnValue("ok");
  ...
  //end behavior definition
  control.replay();
  ...
  
  MockControl中超过50个方法是行为定义方法。他们可以如下分类。
  
  o    setReturnValue()
  
  这些方法被用来定义最后的方法调用应该返回一个值作为参数。这儿有7个使用原始类型作业参数的`setReturnValue()方法,如setReturnValue(int i)或setReturnValue(float f)。setReturnValue(Object obj)被用来满足那些需要对象作为参数的方法。如果给定的值不匹配方法的返回值,则抛出AssertionFailedError异常。
  
  当然也可以在行为中加入预期调用的次数。这称为调用次数限制。
  
  MockControl control =
  ... 网管联盟bitsCN_com
  Foo foo = (Foo)control.getMock();
  ...
  foo.bar(10);
  //define the behavior -- return "ok" when the
  //argument is 10. And this method is expected
  //to be called just once.
  setReturnValue("ok", 1);
  ...
  
  上面的代码段定义了bar(10)方法只能被调用一次。如果提供一个范围又会怎么样呢?
  ...
  foo.bar(10);
  //define the behavior -- return "ok" when the
  //argument is 10. And this method is expected
  //to be called at least once and at most 3
  //times.
  setReturnValue("ok", 1, 3);
  ...
  
  现在bar(10)被限制至少被调用一次最多3次。更方便的是Range已经预定义了一些限制范围。
  ...
  foo.bar(10);
  //define the behavior -- return "ok" when the
  //argument is 10. And this method is expected
  //to be called at least once.
  setReturnValue("ok", Range.ONE_OR_MORE);
  ...
  
  Range.ONE_OR_MORE是一个预定义的Range实例,这意味着方法应该被调用至少一次。如果setReturnValue()中没有定义调用次数限制,如setReturnValue("Hello"),Range.ONE_OR_MORE被认为是缺省值。还有两个预定义的Range实例,Range.ONE(就一次)和Range.ZERO_OR_MORE(对调用次数没有限制)。

网管bitscn_com


  
  这儿还有一个特定的设置返回值的方法:setDefaultReturnValue()。他将代替方法的参数值作为返回值,缺省的调用次数限制为Range.ONE_OR_MORE。这被称为方法参数值敏感性。
  ...
  foo.bar(10);
  //define the behavior -- return "ok" when calling
  //bar(int) despite the argument value.
  setDefaultReturnValue("ok");
  ...
  
  o    setThrowable
  
  setThrowable(Throwable throwable)被用来定义方法调用异常抛出的行为。如果给定的throwable不匹配方法的异常定义,则AssertionFailedError会被抛出。调用次数的限制与方法参数值敏感性是一致的。
  ...
  try {
  foo.dummy();
  } catch (Exception e) {
  //skip
  }
  //define the behavior -- throw ParseException
  //when call dummy(). And this method is expected
  //to be called exactly once.
  control.setThrowable(new ParseException("", 0), 1);
  ...
  
  o    setVoidCallable()
  setVoidCallable()被用于没有返回值的方法。调用次数的限制与方法参数值敏感性是一致的。 网管论坛bbs_bitsCN_com
  ...
  try {
  foo.dummy();
  } catch (Exception e) {
  //skip
  }
  //define the behavior -- no return value
  //when calling dummy(). And this method is expected
  //to be called at least once.
  control.setVoidCallable();
  ...
  
  o   

TAGs对象   介绍   测试   单元   关于   方法   ...   定义   调用   行为    
 上一篇:看 JUnit 中Metedata的巧妙应用   下一篇:Java标准单元测试库 JUnit 4 抢先看
相关文章列表
关于Java单元测试中的伪对象介绍(图) 评论:
loading.. 评论加载中…
评论:请自觉遵守互联网相关政策法规,评论不得超过250字。

验证码: 注册用户
本类热门排行:
1.Spring+hibernate的单元测试Junit
2.用JUnit框架实现Java单元测试
3.JUnit学习笔记之NetBeans入门篇
4.Java标准单元测试库 JUnit 4 抢先看
5.JUnit实施
6.用 Jython 构建 JUnit 测试包
7.开源技术:JUnit常用断言方法
8.JBuilder2005单元测试之JUnit框架
9.关于Java单元测试中的伪对象介绍(图)
10.Java开源项目——突破JUnit的局限
最新推荐文章:
1.Java技术开源搜索引擎
2.名词解释 什么是JUnit?
3.BeanShell 在人工测试与管理中的应用
4.JForum 2.1.7 源程序编译草记
5.检测代码是否有Junit Test Class的小功能
6.轻松测试-学习如何简化测试外部资源
7.Spring+hibernate的单元测试Junit
8.看 JUnit 中Metedata的巧妙应用
9.用 Jython 构建 JUnit 测试包
10.JUnit实施
网管论坛交流:
·不疯魔不成活
·令你大开眼界的真正标准化机房,已整理重
·为赈灾,女孩舍身拍“裸照”
·Windows Server 2003服务器群集创建和配
·exchange2k3全套官方资料
·双儿一周岁了。。。特殊的礼物来啦。。
·存储备份技术版块守则
·无盘技术交流区守则
·DOS命令基础大全之命令详解<作者吐血
·Windows XP 操作系统默认设置需要注意的