背景:
Mock 方法是单元测试中常见的一种技术
它的主要作用是模拟一些在应用中不容易构造或者比较复杂的对象,从而把测试与测试边界以外的对象隔离开,获得一个孤立的测试环境。
在单元测试中,我们常遇到的问题是:
应用中其它的协同模块尚未开发完成,
或者被测试模块需要和一些不容易构造、
比较复杂的对象进行交互。
另外,由于不能肯定其它模块的正确性,我们也无法确定测试中发现的问题是由哪个模块引起的。
注:
不容易构造的对象的例子: HttpServletRequest 必须在 Servlet 容器中才能构造出来
比较复杂的对象的例子: JDBC 中的 ResultSet 对象
EasyMock 简介
手动的构造 Mock 对象会给开发人员带来额外的编码量,而且这些为创建 Mock 对象而编写的代码很有可能引入错误。
目前,有许多开源项目对动态构建 Mock 对象提供了支持,这些项目能够根据现有的接口或类动态生成,这样不仅能避免额外的编码工作,同时也降低了引入错误的可能。
EasyMock 是一套用于通过简单的方法对于给定的接口生成 Mock 对象的类库。
它提供对接口的模拟,能够通过录制、回放、检查三步来完成大体的测试过程,可以验证方法的调用种类、次数、顺序,可以令 Mock 对象返回指定的值或抛出指定异常。
通过 EasyMock,我们可以方便的构造 Mock 对象从而使单元测试顺利进行。
使用 EasyMock 进行单元测试的大致步骤:
a. 使用 EasyMock 生成 Mock 对象;
b. 设定 Mock 对象的预期行为和输出;
c. 将 Mock 对象切换到 Replay 状态;
d. 调用 Mock 对象方法进行单元测试;
e. 对 Mock 对象的行为进行验证。
参考TestCase
public class SalesOrderTestCase extends TestCase {
public void testSalesOrder() {
IMocksControl control = EasyMock.createControl();
......
ResultSet mockResultSet = control.createMock(ResultSet.class);
try {
......
mockResultSet.next();
expectLastCall().andReturn(true).times(3);
expectLastCall().andReturn(false).times(1);
mockResultSet.getString(1);
expectLastCall().andReturn("DEMO_ORDER_001").times(1);
expectLastCall().andReturn("DEMO_ORDER_002").times(1);
expectLastCall().andReturn("DEMO_ORDER_003").times(1);
mockResultSet.getString(2);
expectLastCall().andReturn("Asia Pacific").times(1);
expectLastCall().andReturn("Europe").times(1);
expectLastCall().andReturn("America").times(1);
mockResultSet.getDouble(3);
expectLastCall().andReturn(350.0).times(1);
expectLastCall().andReturn(1350.0).times(1);
expectLastCall().andReturn(5350.0).times(1);
control.replay();
......
int i = 0;
String[] priceLevels = { "Level_A", "Level_C", "Level_E" };
while (mockResultSet.next()) {
SalesOrder order = new SalesOrderImpl();
order.loadDataFromDB(mockResultSet);
assertEquals(order.getPriceLevel(), priceLevels[i]);
i++;
}
control.verify();
} catch (Exception e) {
e.printStackTrace();
}
}
}
其他相关内容:
Mock 对象的行为进行验证,使用verify方法,如:verify(mockResultSet);
Mock 对象的重用,使用rset方法
EasyMock 预定义的参数匹配器
自定义参数匹配器
特殊的 Mock 对象类型:Strick Mock对象和Nice Mock对象
EasyMock的工作原理
EasyMock 后台处理的主要原理是利用 java.lang.reflect.Proxy 为指定的接口创建一个动态代理,这个动态代理,就是我们在编码中用到的 Mock 对象。
EasyMock 还为这个动态代理提供了一个 InvocationHandler 接口的实现,这个实现类的主要功能就是将动态代理的预期行为记录在某个映射表中和在实际调用时从这个映射表中取出预期输出。
参考:
https://www.ibm.com/developerworks/cn/opensource/os-cn-easymock/