同时假定 Collaborator 对象要求使用字符串和原始的 int 作为传递给构造函数的参数。清单 6 显示了对 Collaborator 对象所做的更改。
清单 6. 经过编辑的场景 3 的 Collaborator 类
public class Collaborator{
private String collaboratorString;
private int collaboratorInt;
public Collaborator(String string, int number){
collaboratorString = string;
collaboratorInt = number;
}
public String executeJob(){
return "success";
}
}
Collaborator 类构造函数仍然十分简单。用传入参数设定类字段。这里不必使用任何其他逻辑,并且其 executeJob() 函数保持不变。
重新运行测试,并且示例的所有其他组件保持不变。结果是灾难性的测试失败,如下所示:
图 5. 场景 3 测试失败
以上测试是作为简单的 JUnit 测试运行的,没有代码覆盖。您可以用大多数代码覆盖工具(例如,Cobertura 或 EclEmma)来运行本文中列出的任何一个测试。但是,用 Eclipse 内的代码覆盖工具运行 RMock 测试时会带来一些问题(参见 表 1)。以下代码显示了实际堆栈跟踪的代码片段。
清单 7. 场景 3 中测试失败的堆栈跟踪
...Superclass has no null constructors but no arguments were given
at.net.sf.cglib.proxy.Enhancer.emitConstructors(Enhancer.java:718)
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:499)
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:660)
.....
.....
失败原因是 jMock 无法通过没有无参数构造函数的类定义创建可行的模拟对象。实例化 Collaborator 对象的惟一方法是提供两个简单参数。您现在必须找到一种方法把参数提供给模拟对象实例化过程以达到同样的效果,这就是使用 RMock 的原因。
用 RMock 测试框架更正失败的测试
要更正测试,必须执行一些修改。这些更改可能显得十分重要,但是实际上,它们是一种相对简单的解决方法,利用两种框架的强大功能来实现目的。
必需的第一项更改是使测试类成为 RMock TestCase,而不是成为 jMock CGLIB TestCase。目的是在测试本身内启用属于 RMock 的那些模拟对象的较容易的配置并且 —— 更重要的是 —— 在最初设置期间启用这些配置。经验证明,如果测试类扩展的整个 TestCase 对象属于 RMock,则通过两个框架构造和使用模拟对象将更容易。此外,乍看之下,快速确定模拟对象的流程将更容易一些(在这里,流程 用于描述使用模拟对象作为参数甚或作为其他模拟对象的返回类型的情况)。
必需的第二项更改是(至少)构造一个保存传递给 Collaborator 类的构造函数的参数实际值的对象数组。为了清晰起见,还可以包括构造函数接受的类类型的类型数组并可以传递该数组,以及刚刚描述为参数的对象数组以实例化模拟 Collaborator 对象。
第三项更改涉及用正确语法构造对 RMock 模拟对象的一个或多个期望。而第四项也是最后一项必需的更改是使 RMock 模拟对象脱离记录状态转入就绪状态。
实现 RMock 更改
清单 9 显示了对 ServiceClassTest 类的最终修改。它还显示了 RMock 及其相关功能的引入。
清单 9. 修正场景 3 的 ServiceClassTest 类
110593_2009040210090319Miv
文章来源于领测软件测试网 https://www.ltesting.net/