EasyMock与JMock的比较

本文对比了EasyMock和jMock在模拟类、方法、参数及返回值的功能,展示了它们的行数差异及具体类模拟能力。讨论了如何选择适合的库,特别关注了对构造参数的支持,提供了比较表格并推荐了使用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MockObjects的选择:EasyMock与JMock的比较

本文假设读者已经了解了MockObjects的使用目的和基本方式,不对MockTest之类的技术作过多解释。仅提醒一句:“不要测试你的MockObjects”。

本文作为一个评测结果的同时,也可以作为EasyMock和jMock的简短教程。他们本身都很易用,可惜带的示例过于复杂,都用了过多的模式。看过本文的例子,相信就可以从容的在项目中使用了。

Java中常用的MockObjects有EasyMock和jMock等。其中EasyMock开发较早,已经出了1.1版本,而jMock前几天才刚推出了1.0 final。作为刚成熟的小弟弟,jMock有什么竞争实力呢?

本比较针对于以下几个方面,代码请见附件。

1 是否能够对具体类进行模拟(当然,对接口模拟是基本功能)

2 是否能够对方法名,参数,返回值进行动态控制

3 基本代码行数

4 是否能够对具有构造参数的具体类模拟

现在比较开始了。首先制作若干测试文件,很简单。要模拟的有一个接口和一个具体类,叫做TheInterfaceToMock和TheClassToMock,另外,提供方法SampleReturn sampleMethod(Parameter p);以及同名无参数方法。

第一个测试是针对TheInterfaceToMock,提供ParameterImpl和SampleReturnImpl作为期待的参数和返回值。

jMock代码如下:

public class JMockUsage extends MockObjectTestCase {

public void testReturnValueWithParemeter(){

// 构造Mock控制器

Mock m = new Mock(TheInterfaceToMock.class);

// 这是要测试MockObject

TheInterfaceToMock mock = (TheInterfaceToMock) m.proxy();

// 期待的返回值

SampleReturn sr = new SampleReturnImpl();

// 期待的参数

Parameter p = new ParameterImpl();

// 控制器,期待一次,方法sampleMethod,参数等于p(equals),将返回sr

m.expects(once()).method("sampleMethod")

.with(eq(p)).will(returnValue(sr));

// 正式执行mockobject

SampleReturn ret = mock.sampleMethod(new ParameterImpl());

// 确定返回值是相同的

assertSame(sr,ret);

}

}

相同功能的easyMcok代码如下:

public class EasyMockUsage extends TestCase {

public void testReturnValueWithParameter(){

// 构造mock控制器

MockControl control

= MockControl.createControl(TheInterfaceToMock.class);

// 这是要测试的MockObject

TheInterfaceToMock mock

= (TheInterfaceToMock) control.getMock();

// 这是要返回的值

SampleReturn sr = new SampleReturnImpl();

// 这是要传入的参数

Parameter p = new ParameterImpl();

// 恢复到记录(record)状态

control.reset();

// 首先记录sampleMethod方法

mock.sampleMethod(p);

// 设定该方法的返回值

control.setReturnValue(sr);

// 切换状态为回复(reply)

control.replay();

// 正式执行mock object的方法,明显的,参数值是equals而不是same

SampleReturn ret = mock.sampleMethod(new ParameterImpl());

// 确定返回值是需要的值

assertSame(sr,ret);

}

从上面的代码可以看到,同样的功能,二者的行数相差3行。其主要原因,就是easyMcok的Mock机制是基于状态,首先是录制状态,记录下来待测的方法和参数,返回值等,然后切换为回复状态。而jMock没有切换这一步,直接将参数返回值用一句话写出来。确实是一句话:期待一次,方法sampleMethod,参数等于p(equals),将返回sr。其中的一些辅助函数,例如returnValue,eq等等,位于父类MockTestCase。

结论

1 如果不能提供MockTestCase作为父类,请使用EasyMock

2 如果需要批量或动态生成测试,请使用更规则的jMock

3 如果喜欢看起来行数少一些,请用jMock

4 如果对状态切换看不顺眼,请用Mock

下面进行具体类测试,一个共同的点是,二者均使用了CGLIB作为增强器,因此效率差别几乎没有。将上面的测试稍稍修改,将TheInterfaceToMock改为TheClassToMock。发生了以下变化。

用jMock,需要将import替换为新的import,代码中其他部分完全不变!

原来

import org.jmock.Mock;

import org.jmock.MockObjectTestCase;

改为:

import org.jmock.cglib.Mock;

import org.jmock.cglib.MockObjectTestCase;

这是个相当体贴的设计,保证了接口的一致性。对于一套API来说,同样的类却有不同的使用方法是个噩梦。

用easyMock,需要新增加一个import。并且修改一些声明的地方。

原来

import org.easymock.MockControl;

增加

import org.easymock.classextension.MockClassControl;

// mock控制器

MockControl control = MockClassControl.createControl(TheClassToMock.class);

其他部分不需要变化。虽然这有些变化,但是变化带来了其他的好处,就是:能够支持带有构造参数的具体类,而jMock不支持。这对于大量使用了PicoContainer的代码来说不啻是一个福音。

结论

5 如果需要构造参数,只能使用easyMock

6 如果喜欢用相同的API操作并且不在乎构造参数,请用jMock

7 如果愿意等待下一版本的jMock提供构造参数支持,请用jMock

参考比较表:

EasyMock

jMock

通过接口模拟

控制方法有效次数

定制参数匹配

不需要状态转换

具体类模拟

具体类可有构造参数

接口统一

条件代码在一行中完成

支持其他参数规则,如not

自验证 verify()

综上,我选择了jMock。不过想想看,easyMock用3个类实现了大多数常用功能,很不简单啊。而jMock,如果能够提供对Constructor injection的支持就完美了。遗憾。不过从设计上看,jMock里的模式使用堪称典范,很好看哦。

本人对easyMock使用经验不多,如有谬误请指出。

下载地址:

http://www.jmock.org

http://www.easymock.org

比较代码:

http://icecloud.51.net/data/mockobjects.zip

需要:

JUnit3.8.1,Cglib2,jMock1.0,EasyMock1.1


版权声明:
本文由冰云完成,作者保留中文版权。
未经许可,不得使用于任何商业用途。
欢迎转载,但请保持文章及版权声明完整。
如需联络请发邮件:icecloud(AT)sina.com
Blog:http://icecloud.51.net

Jmockdata(再也不用苦逼的造测试数据了) Jmockdta是一款实现模拟JAVA类型或对象的实例化并随机初始化对象的数据的工具框架。单元测试的利器。     The plug-in of Jmockdata what through random algorithm mock java data.   Jmockdata插件通过随机算法模拟Java数据.   版本信息 Jmockdata-2.0 发布时间 2017-02-03 Jmockdata-1.0 发布时间 2017-01-04 具体介绍和用法可以参考如下:   0. 模拟数据入口方法 JMockData.mock(JmockDataWrapper) 1. 被模拟数据必须继承JmockDataWrapper经过它的包装 2. 被模拟的数据最好是plain bean,只提供getter,setter,has,is方法的才可以被模拟 3. 框架默认实现了40个元数据类型的数据模拟器包括:   byte.class,Byte.class,byte[].class,Byte[].class, short.class,Short.class,short[].class,Short[].class, int.class,Integer.class,int[].class,Integer[].class, long.class,Long.class,long[].class,Long[].class, float.class,Float.class,float[].class,Float[].class, double.class,Double.class,double[].class,Double[].class, boolean.class,Boolean.class,boolean[].class,Boolean[].class, char.class,Character.class,char[].class,Character[].class, String.class,String[].class, BigDecimal.class,BigDecimal[].class, BigInteger.class,BigInteger[].class, Date.class,Date[].class 通过对以上基本元数据类型的模拟实现,本框架可以轻松模拟由以上元数据结构组成的BEAN、LIST、SET、ARRAY等复杂深度的数据结构的数据模拟。   4. 可以通过JmockDataContext 获取模拟过程的所有上下文信息,甚至可以打印整个模拟类型树   5. 可以通过JMockDataManager 注册模拟数据类型,重写模拟数据算法,注册模拟数据类拦截器等 6. 可以通过实现MockData来实现一个模拟数据类型 7. 可以通过实现JmockDataTemplate,或者继承JmockDataTemplateDefault来重写模拟数据算法 8. 可以通过实现JmockDataInterceptor来实现一个拦截器 9. 具体示例实践请参考https://github.com/jsonzou/jmockdata-demo 10. 有问题或者对本框架有新的想法,请联系我, 作者:jsonzou 标签:Jmockdata
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值