清单 10. 场景 4 的测试示例
public class MyNewClassTest extends RMockTestCase{
private MyNewClass myClass;
private MockObjectTestCase testCase;
private Collaborator collaborator;
private Mock mockClassB;
public void setUp(){
myClass = new MyNewClass();
testCase = new MyMockObjectTestCase();
mockClassB = testCase.mock(ClassB.class, "mockClassB");
mockClassB.expects(testCase.once()).method("wierdMethod").
will(testCase.returnValue("passed"));
Class[] someClassArray = new Class[]{String.class, ClassA.class, ClassB.class};
Object[] someObjectArray = new Object[]
{"someArbitraryString", new ClassA(), (ClassB)mockClassB.proxy()};
collaborator = (Collaborator)intercept
(Collaborator.class, someClassArray, someObjectArray, "mockCollaborator");
}
public void testRMockAndJMockInCollaboration(){
startVerification();
assertTrue(myClass.executeJob(collaborator));
}
private class MyMockObjectTestCase extends MockObjectTestCase{}
private class MyNewClass{
public boolean executeJob(Collaborator collaborator){
collaborator.executeSomeImportantFunction();
return true;
}
}
}
在 setUp() 方法内,根据为扩展 jMock-CGLIB MockObjectTestCase 对象而创建的私有内部类实例化了新 "testcase"。使用任何 jMock 功能时,这个小解决方法对于确保整个测试类为 RMock TestCase 对象十分有必要。例如,您将设定类似 testCase.once() 而不是类似 once() 的 jMock 期望,因为 TestClass 对象将扩展 RMockTestCase。
构建基于 ClassB 类的模拟对象并向其提供期望。然后您将使用它帮助实例化 RMock Collaborator 模拟对象。待测试的类是 MyNewClass 类(在这里显示为私有内部类)。同时,其 executeJob() 方法将接收 Collaborator 对象并运行 executeSomeImportantFunction() 方法。
清单 11 和 12 分别显示了 ClassA 和 ClassB 的代码。ClassA 是没有实现的简单类,而 ClassB 显示了阐明要点所需的少细节。
清单 11. ClassA 类
public class ClassA{}
此类只是我使用的一个虚构类,用于强化一个要点:要模拟构造函数接收对象参数的类,有必要使用 RMock。
清单 12. ClassB 类
public class ClassB{
public ClassB(){}
public String wierdMethod(){
return "failed";
}
}
ClassB 类的 wierdMethod 将返回 failed。这是十分重要的,因为该类必须简短地返回另一个字符串才能使测试通过。
清单 13 显示了测试示例的重要部分:Collaborator 类。
清单 13. Collaborator 类
public class Collaborator {
private String _string;
private ClassA _classA;
private ClassB _classB;
public Collaborator(String string, ClassA classA, ClassB classB) throws Exception{
_string = string;
_classA = classA;
if(classB.wierdMethod().equals("passed")){
_classB =classB;
}
else{
throw new Exception("Something bad happened");
}
}
public void executeSomeImportantFunction(){
}
}
注,首要的是,使用 jMock 框架模拟了 ClassB 类。使用 RMock,没有一种实际方法从模拟对象中提取和使用代理,以便在测试 setUp() 方法中的其他位置使用该代理。使用 RMock,仅当调用 startVerification() 方法之后,才显示代理对象。本例中的优点是使用 jMock,因为在需要返回自我模拟对象的情况下,可以 获得设置其他模拟对象所需的信息。
反过来,需要注意的第二点是您不能使用 jMock 框架来模拟 Collaborator 类。原因是该类没有无参数构造函数。此外,在构造函数内有某种逻辑,这种逻辑将确定是否先获得实例。事实上,出于本次讨论的目的,ClassB 中的 wierdMethod() 方法必须返回 passed 才能使 Collaborator 对象被实例化。但是,另请注意,在默认情况下,方法总是返回 failed。测试成功明显需要模拟 ClassB。
此外,不同于先前的示例,此场景中的类数组作为附加参数被包含到了 intercept() 方法中。对此不作严格要求,但是用它作为密钥可以快速识别在实例化 RMock 测试对象时使用的对象类。