关闭

使用配置文件定义 Mock 对象,创建高效、灵活的测试用例

发表于:2007-10-30 12:13

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:郑闽睿 黄湘平    来源:网络转载

  在对 Mock 对象的方法调用进行配置以后,我们接下来对方法的预期输出进行配置。方法的预期输出定义包含在 <ctrlOptions> 中。<ctrlOption> 中的 option 属性指定了 MockControl 对象在指定方法返回值时选用的选项。Option 属性可选的值包括:

  • andReturn
  • andStubReturn
  • andThow
  • andSubThrow
  • andVoidCallable

  其中,andReturn 选项用于设定方法的预期返回值,当 option 属性为 andReturn 时,我们可以在 value 属性中配置方法的返回值。在预期方法确定以后,其返回值类型也确定了,因此我们无需在此指定返回值类型。times 属性用于指定预定方法的调用次数。如果希望为 Mock 对象方法设置默认的预期返回值,那么你可以选择 andStubReturn,这时 value 属性中的返回值将作为预期方法的固定返回值,而无需多次设定。

  andThrow 选项用于设定预期异常抛出。当 option 属性为 andThrow 时,value 属性用于指定预期的异常类型。times 属性同样用于设定预期异常抛出的次数。如果希望为 Mock 对象方法设定默认的异常抛出,您可以相应的选择 andSubThrow。

  如果预期方法的返回值为空(void),那么您应当指定 andVoidCallable 方法。这时 value 属性不用设定(如果设定,XMLEasyMock会忽略该属性)。

  我们仍然用 ResultSet 接口的 getString 方法为例,说明预期输出的配置效果:


清单5:Mock对象预期行为定义
<mockBehavior mockObject="mockResultSet" method="getString">
  ......
  <ctrlOptions>
    <ctrlOption option="andReturn" value="My return value" times="1" />
    <ctrlOption option="andThrow" value="java.sql.SQLException" times="2" />
  </ctrlOptions>
</mockBehavior>

  以上的配置相当于在 EasyMock 中调用:

expectLastCall().andReturn("My return value").times(1);
expectLastCall().andThrow(new SQLException()).times(2);

  XMLEasyMock 中为每个 Mock 对象的预期行为创建一个 MockBehavior 对象。MockBehavior 类中包含了两个列表,分别包含了多个 ParamValue 对象和 CtrlOption 对象。所有 MockBehavior 对象都由 MockBehaviorController 统一管理。MockBehaviorController 提供了 loadMockBehaviorsrunMockBehaviors 方法,分别用于读入 MockBehavior 和执行预期行为设定。这些类的关系如下图所示:

图3:设定 Mock 对象预期行为相关类图
设定 Mock 对象预期行为相关类图

  XMLEasyMock 对 Mock 对象预期方法是通过类反射机制进行调用的。如图4所示,当 MockBehavior 的 runMockMethod 方法被调用时,它首先通过 Mock 对象名查询 Mock 对象,接着从 ParamValue 中取出用户设定的参数类型和参数值。根据 Mock 对象的类型、Mock 对象的方法名和参数类型列表,我们可以通过 Class 的 getDeclaredMethod 获取到对应的 Method 对象。最后,runModkMethod 方法调用 Method 对象的 invoke 方法,完成 Mock 对象预期方法的调用。


图4:Mock 对象预期方法调用时序图
Mock 对象预期方法调用时序图

  在对预期方法进行调用之后,我们需要通过 EasyMock 类对方法的预期输出进行设定。我们以设定预期返回值为例进行说明(设定预期异常抛出与此类似)。


图5:设定 Mock 对象预期输出时序图
设定 Mock 对象预期输出时序图

  如图5所示,MockBehavior 类提供了 runCtrlOptions 用于设定方法的预期输出。runCtrlOption 方法首先调用之前得到的 Method 对象的 getReturnType 方法,获取方法的返回值类型,并将该返回值类型作为参数传递给 CtrlOption 的 runCtrlOption 方法。runCtrlOption 方法首先调用 EasyMock 类的 expectLastCall 静态方法,获得 Mock 对象所对应的 IMocksControl 实例,之后,根据预期方法的返回值类型对配置文件中的返回值进行格式化,将格式化后的数据作为参数传递给 IMocksControl 的 andReturn 方法,最后,调用 times 方法设定预期调用次数。

  以上是 XMLEasyMock 对 Mock 对象生成、Mock 对象预期行为设定的具体实现。对于外部程序而言,只需要调用 EasyMockUtil 提供的 loadConfig 静态方法就可以达到根据配置文件构建 Mock 对象的目的了:


图6:构建 Mock 对象和设定预期行为时序图
构建 Mock 对象和设定预期行为时序图

  EasyMockUtil 的 loadConfig 方法 MockObjectController 的 loadMockObjects 方法和 MockBehaviorController 的 loadMockBehaviors 方法读取和创建 Mock 对象及其预期行为。MockBehaviorController 的 runMockBehaviors 先后调用 runMockMethod 和 runCtrlOptions 方法设定 Mock 对象的预期方法调用和预期输出。最后,loadConfig 方法调用 MockObjectController replay 方法将 Mock 对象切换成 Replay 状态。

4.利用 Mock 对象定义机制配置预期结果

  在进行单元测试时,被测试模块的预期结果也编码在代码中,当测试数据或是测试用例发生变化时,预期结果也将发生改变。我们是否能将预期结果也定义在配置文件中呢?

  我们可以将被测试的对象在正确运行的情况下的行为抽象为一个 Mock 对象,它的预期输出,就是被测试对象在正确运行情况下的预期输出。通过这种方式,我们就可以用类似配置 Mock 对象的方式对预期结果进行配置了。在 XMLEasyMock 中我们提供了一个测试用的接口 SalesOrder,它的实现类 SalesOrderImpl 的主要功能是从数据库中读取一个 Sales Order 的 Region 和 Total Price,并根据读取的数据计算该 Sales Order 的 Price Level:

43/4<1234>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号