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
|
分享到:
相关推荐
4. **组合使用与JUnit**:JMock可以很好地与JUnit等测试框架集成,方便编写和运行测试。 **EasyMock 3.0** EasyMock是另一个流行的模拟框架,它的设计目标是使单元测试变得更加简单。EasyMock 3.0版本引入了一些...
在 EasyMock 中,你可以通过扩展 `EasyMock` 类或使用 `createMock()` 方法来创建 mock 对象。例如,如果你有一个名为 `MyService` 的接口,你可以这样创建它的 mock 实例: ```java MyService myServiceMock = ...
【标题】"5-Mock+EasyMock.rar" 涉及到的是软件开发中的测试技术,特别是关于模拟对象(Mock Objects)和EasyMock框架的应用。在软件开发中,特别是使用面向对象编程时,Mock对象是一种重要的测试策略,它用于替代...
EasyMock与其它模拟工具的比较** EasyMock与Mockito、PowerMock等工具相比,各有优缺点。EasyMock适合简单的模拟场景,而Mockito提供了更丰富的功能和更简洁的API。PowerMock则可以模拟静态方法、构造函数等不易...
5. 构建EasyMock:根据项目说明,使用Maven或Gradle等构建工具编译源码。 6. 配置与启动:根据EasyMock的文档,配置相应的环境变量和依赖,然后启动服务。 在Windows环境中部署EasyMock可能涉及一些额外的配置,...
EasyMock 是一个用于生成模拟对象(Mock Object)的类库,主要用于单元测试。它提供了一种简单的方法来模拟接口或类的行为,使得在测试中可以模拟真实环境中的对象。 EasyMock 的主要特点包括: 简单易用:使用 ...
1. **模拟对象(Mock Objects)**:Easymock的核心就是创建模拟对象,它们可以代替真实的对象参与到测试中。通过模拟对象,我们可以控制方法的调用、预期参数和返回值,确保被测试代码按预期执行。 2. **预期...
在进行单元测试时,EasyMock与JUnit、TestNG等测试框架结合使用,可以提供更完善的测试解决方案。它简化了对依赖对象的管理,让测试更加专注和可控。 至于压缩包中的“面试经典.pdf”和“笔试题集.pdf”,这些可能...
1. **模拟对象(Mock Object)**:EasyMock允许我们创建模拟对象,这些对象可以模仿真实对象的行为,但不会执行实际的业务逻辑。这样,我们可以在测试中专注于代码的单一行为,而不受其他依赖的影响。 2. **期望...
1. **模拟对象(Mock Objects)**:在单元测试中,模拟对象是代替真实对象的替代品,它们根据预设的行为返回特定的结果。Easymock可以帮你生成这些模拟对象,以便在测试中控制依赖。 2. **期望值(Expectations)**...
EasyMock 是一套用于通过简单的方法对于给定的接口生成 Mock 对象的类库,旨在解决单元测试中的 Mock 对象构建问题。以下是 EasyMock 的详细介绍: 单元测试与 Mock 方法 单元测试是对应用中的某一个模块的功能...
1. EasyMock:EasyMock是一个Java库,用于创建和运行模拟对象,以帮助测试代码。在TDD中,我们经常需要隔离被测试的代码,以便于单独测试其行为。EasyMock允许开发者定义预期的行为,模拟合作对象的响应,这样即使在...
7. **Mockito集成**:EasyMock 3.1还支持与另一个流行的测试库Mockito的集成,这使得开发者可以利用两者的优点,扩展测试能力。 在实际使用中,你需要将EasyMock的jar包添加到你的项目构建路径中。然后,你可以创建...
EasyMock 是一套用于通过简单的方法对于给定的接口生成 Mock 对象的类库。它提供对接口的模拟,能够通过录制、回放、检查三步来完成大体的测试过程,可以验证方法的调用种类、次数、顺序,可以令 Mock 对象返回指定...
5. **扩展EasyMock**:EasyMock还可以与其它库结合,如`EasyMock.ClassExtender`用于创建扩展已有的类的模拟对象。 6. **Nice Mocks 和 Strict Mocks**:Nice Mocks默认允许所有未预期的调用,而Strict Mocks则会抛...
- EasyMock支持扩展,可以与其他框架(如CGLIB)结合,模拟无接口类或final方法。 **Mockito** Mockito是一个功能更加强大的模拟框架,它提供了更加简洁和灵活的API。Mockito不仅支持模拟对象,还提供了诸如验证...
- **相同点**:Mock与Stub都用于实现系统隔离,即在测试过程中,用它们来替代次要对象(即依赖项),使得测试能够集中关注于主要测试对象的功能和行为。 - **不同点**: - **类实现方式**:Stub具有一个显式的类...
Mock 方法是单元测试中常见的一种技术,它的主要作用是模拟一些在应用中不容易构造或者比较复杂的对象,从而把测试与测试边界以外的对象隔离开。 编 写自定义的 Mock 对象需要额外的编码工作,同时也可能引入错误...
JMock可以与多种测试框架集成,如JUnit、TestNG等,也可以与其他模拟库如EasyMock、Mockito配合使用,以满足不同测试需求。 总之,JMock是Java开发者进行单元测试的重要工具,它通过提供模拟和预期机制,帮助确保...
EasyMock允许开发者模拟类的行为,包括设置方法的返回值和抛出异常,这与描述中的"特征 1 为存根方法返回值 2 为存根方法抛出异常"相对应。 首先,让我们深入理解EasyMock的基本概念。EasyMock是一个动态代理库,它...