目前在做一些unit test, 目的是为了得到较高的代码覆盖率,所以就使用了EasyMock + PowerMock, 基本上可以解决unit test中的绝大部分的问题。现在将一些记录如下以做参考:
PowerMock的介绍和基本用法可参照: http://blog.csdn.net/jackiehff/article/details/14000779
以下是用到的一些复杂的用法:
1. 使用TestNG + EasyMock + PowerMock来开发unit test
实例:
@PrepareForTest({FrontControllerServlet.class, Util2.class})
public class FrontControllerServletTester extends PowerMockTestCase {
......
}
说明: a. 将需要由PowerMock处理的类加入到PrepareForTest中。
b. 让测试类继承PowerMockTestCase。
1. Mock 任意参数
EasyMock提供了方法,可以模拟任意参数的值,实例:
EasyMock.expect(sessionFactory.create(EasyMock.<String>anyObject(), EasyMock.<String[]>anyObject(), EasyMock.anyLong()).andReturn(sessionInfo).times(1);
2. Mock 静态方法
a. 有返回值:
静态方法: ApplicationContext.getObject()
实例:
PowerMock.mockStatic(ApplicationContext.class);
configs = EasyMock.createMock(Configs.class);
EasyMock.expect(ApplicationContext.getObject(Configs.class).andReturn(configs).times(1);
b. 无返回值:
静态方法: ValidatorRules.validateTokenVersion
实例:
PowerMock.mockStatic(ValidatorRules.class);
ValidatorRules.validateTokenVersion(request, ErrorCode.TOKEN_EXTEND_TIME_EXPIRE);
PowerMock.expectLastCall().times(1);
Mock 私有方法
实例:
PowerMock.mockStaticPartial(FrontControllerServlet.class, "populateUserMonitor",);
tester = PowerMock.createPartialMock(FrontControllerServlet.class, "populateUserMonitor","setExpiryTimeRespHeader");
PowerMock.expectPrivate(tester, "populateUserMonitor", userIds);
PowerMock.expectPrivate(tester, "setExpiryTimeRespHeader", response).times(2);
PowerMock.replay(FrontControllerServlet.class);
说明: a. populateUserMonitor()是一个静态的私有方法,需要使用mockStaticPartial先做静态的方法。
b. setExpiryTimeRespHeader是一个一般的私有方法,可以直接使用在createPartialMock中。
c. 使用PowerMock.expectPrivate来mock私有方法.
d. 最后需要replay所mock到的类。
2. 直接测试类中的私有方法
目前发现只有使用反射才能直接测试私有方法,示例如下
private void runPrivateNoResult(String methodName, Object... arguments) throws InvocationTargetException, IllegalAccessException {
for (int i = 0; i < methods.length; i++) {
Method method = methods[i];
if (method.getName().equals(methodName)) {
method.setAccessible(true);
method.invoke(tester, arguments);
}
}
}
传入方法名和参数,代码中的tester是要测试的类的实例。