网站首页
JSP空间
动态资讯
开源项目
技术文档
资源下载
J2EE资源
客户论坛
在线支付
 
  技术文档>>JAVA>>新手入门>>基础入门>查看文档  
  关于java单元测试中的伪对象介绍(图)     
  文章作者:未知  文章来源:水木森林  
  查看:86次  录入:管理员--2007-11-17  
 
  在单元测试的策略中伪对象被广泛使用。他从测试中分离了外部的不需要的因素并且帮助开发人员专注于被测试的功能。
  
  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显示了伪对象的生命周期。
   关于java单元测试中的伪对象介绍(图)(图一)
  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的区别。
  关于java单元测试中的伪对象介绍(图)(图二)
  下面是每一个工厂方法的两个不同版本。
  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();
  
  ?行为定义方法
  
  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) {
  ...
  }
  }
  
  伪对象的行为可以按照下面的方式来定义:
  
  //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 =
  ...
  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(对调用次数没有限制)。
  
  这儿还有一个特定的设置返回值的方法: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()被用于没有返回值的方法。调用次数的限制与方法参数值敏感性是一致的。
  ...
  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
 
 
上一篇: 浅析java中常见的date类的应用技巧    下一篇: apache目录服务器中存储java对象
  相关文档
struts行为测试框架strutstestcase实战 11-16
java设计模式之bridge(抽象和行为分开) 11-17
开天劈地:开发java程序的新武器 11-17
atan 方法 11-16
介绍jsr184(3d)中的光线概念 11-17
java基础:正则表达式的简单应用实例 11-16
整合hibernate3与jboss 3.2.x 11-17
java抽取word和pdf格式文件的四种武器 11-17
jsp速成教程 11-17
用jms客户端利用空闲的计算机资源 11-17
java servlet 编程及应用之二 11-16
java 学习之道 11-17
介绍jsp程序动态网站环境搭建的详细步骤 (1) 06-23
servlet容器工作原理讲解(二) 11-17
java违例控制 11-16
java模式研究之flyweight模式 11-16
scjp考试心得集 11-17
如何在netbeans中设置数据库连接池详解 11-16
threadlocal的设计与使用 11-17
j2ee 组件开发:什么是消息驱动的ejb 11-16
返回首页 | 关于我们 | J网章程 | JSP空间合租 | 客服中心 | 免责声明 | 常见问题 | 参观机房
本站主机空间代理至厦门市华众网络科技有限公司
《中华人民共和国增值电信业务经营许可证》
编号:闽B2-20050079
@2005-2008福建JSP技术网 版权所有 闽ICP备05000928号
技术电话:13616026886
邮箱:admin@fjjsp.com 站长QQ,点击这里给我发消息