一、Mock对象
测试是个好习惯,然而当你想测试自己的代码,而依赖的其他类或方法又还没实现。或者你在实践TDD(测试驱动开发),还没完成你的实现,而又想先测试。该怎么办呢?
简单情况可以手动编写mock类,复杂情况可以借助EasyMock等Mock框架来模拟这些类和方法。
mock 测试只是在无法使用真实类时的聊胜于无,如果能够使用真实的依赖项,就不要使用mock。
二、应用场景
1、要测试的模块依赖于不受控的第三方服务或其它组员未完成的服务。
2、涉及到数据库操作,连接不了数据库或不想测试结果改动到数据库时。
3、模块依赖于spring容器注入其它服务实例,但又不想启动spring容器。
4、测试异常。例如创建模拟网络故障的mock。
……
三、具体使用方法
1、创建mock对象
EasyMock实例化的对象基于接口或者类
EasyMock.createMock(要模拟的成员变量类型);
// ICalcMethod 是一个要mock的对象
ICalcMethod calcMethod = EasyMock.createMock(ICalcMethod.class);
2、定义mock行为
1)有返回值
expect()方法指定要模拟方法的方法和参数,andReturn()方法定义方法的返回值,times()方法定义mock对象可以调用多少次。
Easymock.expect(模拟成员的某个要模拟的函数).andReturn(期待的返回值)
// 定义mock的期望
EasyMock.expect(calcMethod.calc(Position.BOSS)).andReturn(70000.0).times(2);
EasyMock.expect(calcMethod.calc(Position.PROGRAMMER)).andReturn(50000.0);
2)没返回值
首先模拟成员调用要模拟的函数,然后在后面跟上一句:EasyMock.expectLastCall()
3、模糊参数
有时候要模拟的函数的参数是在程序运行过程中调用的,参数值来自于程序执行结果,这时可以用模糊参数来解决,模糊参数有:
isA、isNull、anyInt等
4、开始测试
在使用mock对象之前需要调用replay()方法使之激活。
EasyMock.replay(模拟成员);
// 激活mock对象
replay(calcMethod);
四、实例
1、要测试的类
public class UserServiceImpl{
private UserDao dao;
public List<String> queryNames(String[] ids) throws Exception{
try{
return dao.getNames(ids);
}catch(Exception e){
throw e;
}
return null;
}
}
该类依赖UserDao,但UserDao可能还没实现,或要靠spring容器来注入
2、测试代码
@Test
public void test() {
String[] ids = {'1','2','3'};
List<String> returnNams = Arrays.asList("a,b,c".split(","));
UserDao userDaoMock = EasyMock.createMock(UserDao.class);//创建模拟成员
EasyMock.expect(userDaoMock.getNames(ids )).andReturn(returnNams);
EasyMock.replay(userDaoMock );//重放Mock对象
UserServiceImpl userServiceImpl = new UserServiceImpl();
userServiceImpl .queryNames(ids);//目标类调用目标方法
EasyMock.verify(userDaoMock );//验证Mock对象
}