qileilove

blog已经转移至github,大家请访问 http://qaseven.github.io/

基于spring与mockito单元测试Mock对象注入

1.关键词
  单元测试、spring、mockito
  2.概述
  单元测试目前已经成为项目中保证代码质量的一种必要方法,对于一些不易构造或者不易获取的对象通过mock的方式进行测试是一种很有效的处理办法。在基于spring的mock测试中,mock对象获取和使用的便利性可以提升单元测试代码的质量。
  3.实现原理
  Mock对象的注入使用注解和反射,对象注入依赖spring框架支持junit4提供的TestExcutionListeners监听器对象,在监听器中将mock对象注入到单元测试类中。
  4.新建对象方式代码
private IAccessServiceaccessService = Mockito.mock(IAccessService.class);
@BeforeClass
public static void beforeClass(){
// 构造并注入Mock对象ICmsProxyService
sceneConfigService.setAccessService(accessService);
}
  5.监听器方式代码
  5.1  实现监听器
  继承DependencyInjectionTestExecutionListener类,
  实现injectDependencies(TestContexttestContext)方法
public class MockitoDependencyInjectionTestExecutionListener extends
DependencyInjectionTestExecutionListener {
@Override
protected void injectDependencies(TestContext testContext) throws Exception {
super.injectDependencies(testContext);
init(testContext);
}
  5.2 利用反射注入mock对象
private void init(final TestContext testContext)throws Exception {
Object bean = testContext.getTestInstance();
Field[] fields = bean.getClass().getDeclaredFields();
for (Field field : fields) {
Annotation[] annotations = field.getAnnotations();
for (Annotation annotation : annotations) {
if(annotationinstanceof Mock){
//注入Mock实例
MockObject obj = new MockObject();
obj.setType(field.getType());
obj.setObj(Mockito.mock(field.getType()));
field.setAccessible(true);
field.set(bean, obj.getObj());
mockObjectMap.put(field.getName(), obj);
}else if(annotation instanceofAutowired){
injectFields.add(field);
}
}
}


AutowireCapableBeanFactory factory =testContext.getApplicationContext().getAutowireCapableBeanFactory();
//Autowired注解注入mock对象
for (Field field :injectFields) {
field.setAccessible(true);
Object object = field.get(bean);
if(objectinstanceof Proxy){
Class targetClass = AopUtils.getTargetClass(object);
if(targetClass ==null)
return;
Field[] targetFields =targetClass.getDeclaredFields();
for(Field targetField : targetFields){
targetField.setAccessible(true);
if(mockObjectMap.get(targetField.getName()) ==null){
continue;
}
targetField.set(getTargetObject(object,mockObjectMap.get(targetField.getName()).getType()),mockObjectMap.get(targetField.getName()).getObj());
}
}else{
Object realObject = factory.getBean(field.getName());
if(null != realObject){
Method[] methods = realObject.getClass().getDeclaredMethods();
for (Method method : methods) {
if(method.getName().equalsIgnoreCase("set" +field.getName())){
method.invoke(realObject, mockObjectMap.get(field.getName()).getObj());
}
}
}
}
}
}
  5.3 测试类配置
  使用@TestExecutionListeners注解,引入监听器,需要mock的对象加上@Mock注解。
@TestExecutionListeners({MockitoDependencyInjectionTestExecutionListener.class})
public class AccessServiceImplTest extends BaseTestCase{
@Autowired
private IAccessServiceaccessService;
@Mock
private IPersonServicepersonService;
@Mock
private IAccessDaoaccessDao;
}
  6.总结
  监听器的方式解放了代码中硬编码注入mock对象,使得代码简洁干净。

posted on 2014-03-07 10:39 顺其自然EVO 阅读(4989) 评论(0)  编辑  收藏 所属分类: 测试学习专栏


只有注册用户登录后才能发表评论。


网站导航:
 
<2014年3月>
2324252627281
2345678
9101112131415
16171819202122
23242526272829
303112345

导航

统计

常用链接

留言簿(55)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜