使用 Mock 方法能够模拟协同模块或领域对象,从而把测试与测试边界以外的对象隔离开。使单元测试顺利进行。然而,Mock 方法在辅助测试的同时,也给开发或测试人员带来额外的编码工作。另外,由于 Mock 对象本身并不能对测试数据进行管理,因此测试数据的变动和 Mock 对象本身的变动,可能就会极大的增加编译和部署的时间。
本文提出一种利用 XML 文件对 Mock 对象进行配置的机制,并在开源项目 EasyMock 的基础上实现了这种机制。实际上,读者可以基于任何的自己熟悉的 xMock 项目来实现这里的思想。
1.Mock对象的创建方法
开发和测试人员在利用 Mock 方法进行单元测试时发现,编写自定义 Mock 对象会带来大量额外的编码工作:如果为测试中用到的每一个协同模块或领域对象手动编写 Mock 对象,最终的结果将是 Mock 对象的数目随着系统中实际对象数目的增长而增长。此外,这些为创建 Mock 对象而编写的代码也很有可能引入错误。
目前,由许多开源项目对动态构建 Mock 对象提供了支持,这些项目能够根据现有的接口或类动态生成 Mock 对象,从而避免了编写自定义的 Mock 对象,这样不仅能减少一定的编码工作,也可以降低错误引入的可能。
EasyMock 就是这些开源框架中的一个,它是一套通过简单的方法对于给定的接口生成 Mock 对象的类库。它提供对接口的模拟,能够通过录制、回放、检查三个步骤来完成大体的测试过程。EasyMock 可以验证方法的调用种类、次数和顺序,可以令 Mock 对象返回指定的值或抛出指定异常。通过 EasyMock,开发或测试人员能够比较方便的创建 Mock 对象,在一定程度上减少了创建 Mock 对象所带来的工作量。
2.EasyMock 使用示例
EasyMock 的使用方法和原理的详细说明请参见 "EasyMock 使用方法和原理剖析" 一文。在这里,我们仅以 HttpServletRequest 为例对 EasyMock 的功能做简单说明。
在部署到 Servlet 容器之前,需要和 HttpServletRequest 进行交互的模块可以通过构建 Mock 对象的方式进行单元测试。下面是使用 EasyMock(version 2.3)构建 Mock 对象进行简单测试的例子:
清单1:EasyMock 示例
public class HttpServletRequestUtil {
public static boolean validate(HttpServletRequest request) {
String host = request.getHeader("Host");
return host.startsWith("www.ibm.com");
}
}
public class HttpServletRequestTestCase extends TestCase {
public void testHttpSevletRequest() {
HttpServletRequest mockRequest = createMock(HttpServletRequest.class);
mockRequest.getHeader("Host");
expectLastCall().andReturn("www.ibm.com:80").times(1);