`

EasyMock使用说明

阅读更多

开发环境版本

JDK 1.5
JUnit 3.8
EasyMock 2.2
Eclipse 3.1.2
MyEclipse 4.1.0

注:EasyMock2.0+只支持JDK1.5+,因为其代码中用到了很多新增特性,比如for(:)、method(...)等用法。EasyMock最初的1.0版本似乎支持对实体类的模拟,但是貌似在很面的版本中和快就取消了这个功能。

EasyMock介绍

 

EasyMock官方页面

EasyMock provides Mock Objects for interfaces in JUnit tests by generating them on the fly using Java's proxy mechanism. Due to EasyMock's unique style of recording expectations, most refactorings will not affect the Mock Objects. So EasyMock is a perfect fit for Test-Driven Development.

EasyMock是用于JUnit中的虚拟测试辅助包,它提供对interface类的模拟,能够通过录制、回放、检查三步来完成大体的测试过程,可以验证方法的调用种类、次数、顺序,可以令mock对象返回指定的值或抛出指定异常。

下载及安装

EasyMock是放在

sourceforge上的一个开源项目,可以自由下载,从那里下载到对应版本的压缩包后可以直接解压,对于开发,我们只需要easymock.jar这个文件,把它添加到Eclipse的项目jar库里就可以使用了。

另外,由于它是用于在JUnit环境下测试的包,所以在实际使用的时候还需要添加JUnit.jar

概念准备

在正式编程之前,还需要搞懂一些相关概念,这些有的也是类的名字,但是在这里主要是理解他所代表的概念,方便进一步使用EasyMock。

Method、Arguments、Invocation
ExpectedInvocation、actual
MockControl、Mock
reset()、replay()、verify()等。

method、arguments,invocation

这三个概念有从属关系,method代表要模拟的类的一个方法,arguments是这个方法的入口参数,invocation代表一次模拟类的某 个方法的调用,它包含一个method,若干argument(但是在这里不包括返回值)。在EasyMock中有Invocation这个类,含有 Object[] arguments、Method method、Object mock参数。

ExpectedInvocation,actual

前者是代表一次预期的方法调用,这里的预期是指加入了Matcher(s)的Invocation,不仅要具有Invocation的特征,还要加 上对其入口参数的检验器(Matcher),这一概念的引入是为了保证可以判断类似数组这种对象的比较关系,或者为入口参数设定合法条件(不仅是简单的相 等,还有大于等于,字符串的endwith等,用户只要按照它的规则,也可以自己制作专门的matcher)。与其相关的类有 ExpectedInvocation、ExpectedInvocationAndResult、 ExpectedInvocationAndResults,后面两个类加入了指定的返回值,是对有返回值的函数适用的。

而后面的actual是经常出现在EasyMock源代码中作为参数使用的单词,用于代表replay过程中的一次实际的方法调用,和Invocation属于一种概念。

MockControl、Mock

MockControl是控制类,他负责建立整个框架所需的资源,其成员behavior和RecordState state用于保存方法调用的序列,一个control可以同时管理多个mock。Mock对象对应一个你需要测试的待测试类,它会自动建立 JavaProxyFactory<toMock>,再由JavaProxyFactory建立Proxy;同时建立的还有 ObjectMethodFilter(他持有一个MockInvocationHandler对象,对hashCode()、equals()、 toString()三个方法进行判断)和MockInvocationHandler(他持有一个control对象,似乎是用于添加 Invocation序列的)。

reset()、replay()、verify()

reset()方法是将control对象复位,其内部现实是靠新建behavior和state两个对象完成的。replay()是结束录制过 程,他会调用RecordState.closeMethod()方法来完成大部分工作。verify()是用于在录制和回放两个步骤完成之后进行预期和 实际结果的检查。

测试结构模型

接口类:BaseInterface

public interface BaseInterface{
  public void methodABC();
  public SomeValue methodABC(SomeArgument someArgument);
} 

实体类:ImplementsBaseInterface、TargetClass

ImplementsBaseInterface继承了BaseInterface接口,提供方法的具体实现。
public class TargetClass{
  private BaseInterface  member;
  ……//其他成员
  public void somMethods(){
     ……
     member.methodABC();
     member.methodABC(someArguments,……);
  }
  public void setMemeber(BaseInterface  member){
      this.memeber = member;
  }
  ……//其他方法
}

类及方法之间的关系

而TargetClass可能会有一些内部成员,比如现在我们正好有一个BaseInterface类型的内部成员member,而 TargetClass正好有someMethods()需要调用到BaseInterface中的methodABC()和methodABC (SomeArgument someArgument)。

测试类:TargetClassTest

TargetClassTest是一个JUnit Test Case类,用于测试TargetClass这个类,这是我们的目的。

import static org.easymock.EasyMock.*;
import  ……
public class TargetClassTest{
   private TargetClass target;
   private BaseInterface  mock;
   private IMocksControl ctrl;
   public void setUp(){
       ctrl = createStrictControl();
       mock = ctrl.createMock( ImplementsBaseInterface.class ); //建立easymock测试类
       target = new TargetClass();
       target.setMember(mock);   //将刚刚建立的mock加入到target的成员中
   }
   public void testSomeMethods() throws Exception{
       ……//准备工作,生成一些将要使用的对象
       ctrl.reset();  //初始化
       mock.methodABC();
       expect(mock.methodABC(someArguments,……)).andReturn(SomeValue); //由于这个方法有返回值,所以需要用andReturn()方法来指定,否则测试的时候会扔出异常
       ctrl.replay();  //结束整个control的recorder过程,下面进入回放
       target.someMethods();
       ctrl.verify();  //结束回放,进行检查,主要检查回放过程和录制过程是否一致,对于mock对象的方法调用种类、数量、顺序是否符合要求进行验证。如果有错误出现就会抛出异常,但是没有自动检查返回值的功能。
   }
}

对于模型的说明

control

当只有一个mock对象的时候,我们也可以不手动生成control对象,而是直接调用EasyMock类中的createMock(Class clazz)方法,这样的话,相应的reset()、replay()、verify()方法也不能使用control的,而要使用EasyMock类中 的reset(mock)、replay(mock)、verify(mock)方法,只对单一的一个mock对象进行操作,在有多个mock对象的时候 可以做到异步操作(但是这样做似乎意义不大)。但是实际上,control对象是一定会生成的,无论你是否手动生成。

生成control对象的好处在于当有多个mock的时候可以一起执行reset()、replay()、verify()操作。

andReturn()

这个方法只是用于当mock对象的方法需要有返回值的情况下,手动设置这个方法的返回值给调用的测试类的。在本例中methodABC (arguments,……)方法就需要在recorder的时候用andReturn()方法指定返回值给TargetClass。如果对于有返回值的 方法不指定其返回值,在测试的时候会抛出"java.lang.IllegalStateException: missing behavior definition for the preceeding method call XXX"异常。

mock的种类

EasyMock提供了三种Mock类型:StrictMock、NiceMock、Mock。

种类 生成函数 检查顺序 检查方法是否调用 对未说明的方法调用
Mock createMock() 抛出异常
NiceMock createNiceMock() 返回0、null,不抛出异常
StrictMock createStrictMock() 抛出异常

一点补充

对于recorder期的方法调用还有一些设定调用次数的方法比较重要,可能会用到,比如说times(),可以设定调用出现的次数使用方法类似andReturn(value)

expect(***).times(3); //指定这个方法调用出现三次

相当于

expect(***);
expect(***);
expect(***);

还可以设定它出现的次数为不封顶,或在一个范围之内,这些方法都可以在MocksControl类中找到

times(int);
times(min , max);  //将max设为整数最大值就是不封顶,其实设大点也就够用了
anyTimes();
once();

杂谈EasyMock内部原理

看了一天半的时间,对他的原理有了一些认识,但是还不全面,对一些深层的原理还了解得不太清楚,先简单谈一谈目前的认识,很可能会有很多错误的地方,如果以后发现,会陆续修改。


EasyMock是利用线程来捕获mock对象函数调用的,所以他特别有一个LastControl类,里面有三个成员, 用于将线程与三个不同的类相关联,matcher是匹配器、argument是入口参数、control中含有大部分主要内容。

 private static final WeakHashMap<Thread, MocksControl> threadToControl 
 = new WeakHashMap<Thread, MocksControl>();
 private static final WeakHashMap<Thread, Stack<Object[]>> threadToCurrentArguments
 = new WeakHashMap<Thread, Stack<Object[]>>();
 private static final WeakHashMap<Thread, Stack<IArgumentMatcher>> threadToArgumentMatcherStack
 = new WeakHashMap<Thread, Stack<IArgumentMatcher>>();
困惑:matcher和argument应该都是和指定的Invocation相关联,但是这里只存了control,而一个control可以有多个mock,一个mock又能有多个method过程,怎样确定matcher、argument和method的对应关系?是通过线程实现的么?


他将recorder到的method及其参数、times都记录到线性表中,而replay的对应method、参数、times也都记录下来,进行对比,从而实现verify()功能。


Invocation对应一次具体的方法调用过程,可能包含返回值Result。


与之对应的ExpectedInvocation系列类加入了matcher和result,也就是加入了预期的功能。


UnorderedBehavior是最底层的Behavior类,其中主要有addExpected()和addActual ()两个方法,应该可以完成预期的保存和检验两个功能。他有一个ExpectedInvocationAndResults的List,可以记录一些列的 方法预期,可以指定应记录一个mock,但是这点还没有证实。


recorder和replay都是主要靠IMocksControlState接口的实现类:RecorderState和ReplayState,各司其职。


RecorderState的成员是:ExpectedInvocation lastInvocation、Result lastResult、IMocksBehavior behavior behavior用于记录所有提交进来的ExpectedInvocation,而那两个lastXXX,应该是用于保留最后一条记录。verify()方法会直接抛出异常:calling verify is not allowed in record state


ReplayState只有一个IMocksBehavior behavior成员,方法也只有invoke()和verify()不会直接抛出异常。应该是像其名称一样专门用于处理replay时期的验证的 
分享到:
评论
1 楼 zhagener 2012-07-30  
package com.huawei.qyq.impl;

import com.huawei.qyq.IAlarm;

public class Guard {
private IAlarm alarm;

public Guard(IAlarm alarm) {
this.alarm = alarm;
}

public void getBored() {
new Thread() {
@Override
public void run() {
alarm.alarm();
}
}.start();
}
}
请问 :
    怎样才能期待alarm.alarm 抛出异常 ,这个匿名的线程怎样才能mock出来!我也看了网上的http://www.ltesting.net/html/99/n-299.html例子 感觉他直接调了线程的run方法,其实并没有实现多线程并发! 希望你能给我一点指点 ,谢谢!

相关推荐

    EasyMock 使用方法与原理剖析

    EasyMock单元测试的扩展; EasyMock简介(抽象类接口做测试); EasyMock来进行测试; EasyMock如何打桩; EasyMock实践指南;...EasyMock使用技巧;...EasyMock使用说明; EasyMock使用手记; 用Mock object进行隔离测试;

    Easy Mock 详解

    EasyMock单元测试的扩展; EasyMock简介(抽象类接口做测试); EasyMock来进行测试; EasyMock如何打桩; EasyMock实践指南; EasyMock使用技巧;...EasyMock使用说明; EasyMock使用手记; 用Mock object进行隔离测试;

    easymock的使用,含demo

    本文将对 EasyMock 的功能和原理进行介绍,并通过示例来说明如何使用 EasyMock 进行单元测试。 Mock 方法是单元测试中常见的一种技术,它的主要作用是模拟一些在应用中不容易构造或者比较复杂的对象,从而把测试与...

    EasyMock的安装与部署所需全部文件.zip

    为了部署和使用EasyMock,你需要将源码导入一个支持Java开发的IDE(如Eclipse或IntelliJ IDEA),然后按照提供的说明进行编译和配置。 在部署流程中,一般步骤如下: 1. 安装Node.js:访问官网下载Windows安装包,...

    easymock-request.getParamsNames

    本文将详细讲解如何使用 Easymock 对 Servlet 进行单元测试,特别是针对 `HttpServletRequest` 中获取参数的方法 `getParamsNames()`。 在Servlet编程中,`HttpServletRequest` 是一个核心接口,它提供了处理HTTP...

    Easymock教程

    Easymock是一款广泛使用的Java单元测试框架,它允许开发者创建和控制模拟对象,以便在测试过程中隔离被测代码,确保测试的准确性。本教程旨在帮助初学者快速掌握Easymock的基本用法和核心概念。 一、Easymock简介 ...

    EasyMock线上项目迁移工具

    在使用过程中,开发者需要按照工具提供的说明文档,逐步执行迁移步骤,确保所有必要的数据和配置都被正确地转移到本地。 在实际操作中,项目迁移通常涉及以下几个关键步骤: 1. 数据备份:首先,需要从线上环境中...

    test-easymock:带有简单模拟的简单测试

    - **README**:可能提供项目简介、安装和使用说明。 ### Easymock与其它模拟框架对比 Easymock与其他模拟框架如Mockito相比,各有优势。Mockito更注重代码的可读性和简洁性,提供了更丰富的API,而Easymock则更适合...

    easymock-issue-attachments

    EasyMock是一个流行的开源Java库,它允许开发者创建和使用模拟对象来测试代码,而无需实际实现接口或类。这个存储库可能是为了保存和整理在GitHub上无法直接托管的非图像二进制附件,如源代码、日志文件、测试用例或...

    junit:junit,easymock,mockito的使用

    2.easymock的使用实例 3.mockito的使用实例 版本库地址 HTTPS协议: https://github.com/ichunming/junit.git SSH协议: git@github.com:ichunming/junit.git 克隆版本库 操作示例:`$ git clone git@github....

    easymock-4.0.jar中文-英文对照文档.zip

    中文-英文对照文档,中英对照文档,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【***.jar中文文档.zip】,再解压其中的 【***-...

    easymock-4.0.2.jar中文-英文对照文档.zip

    中文-英文对照文档,中英对照文档,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【***.jar中文文档.zip】,再解压其中的 【***-...

    easymock-3.4.jar中文-英文对照文档.zip

    中文-英文对照文档,中英对照文档,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【***.jar中文文档.zip】,再解压其中的 【***-...

    easymock-3.3.jar中文-英文对照文档.zip

    中文-英文对照文档,中英对照文档,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【***.jar中文文档.zip】,再解压其中的 【***-...

    easymock-2.5.jar中文-英文对照文档.zip

    中文-英文对照文档,中英对照文档,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【***.jar中文文档.zip】,再解压其中的 【***-...

    easymock-2.5.2.jar中文-英文对照文档.zip

    中文-英文对照文档,中英对照文档,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【***.jar中文文档.zip】,再解压其中的 【***-...

    easymock-4.3.jar中文-英文对照文档.zip

    中文-英文对照文档,中英对照文档,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【***.jar中文文档.zip】,再解压其中的 【***-...

    easymock-4.1.jar中文-英文对照文档.zip

    中文-英文对照文档,中英对照文档,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【***.jar中文文档.zip】,再解压其中的 【***-...

    easymock-3.5.1.jar中文-英文对照文档.zip

    中文-英文对照文档,中英对照文档,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【***.jar中文文档.zip】,再解压其中的 【***-...

    easymock-3.1.jar中文-英文对照文档.zip

    中文-英文对照文档,中英对照文档,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【***.jar中文文档.zip】,再解压其中的 【***-...

Global site tag (gtag.js) - Google Analytics