1

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

Honwhy 2018年08月09日 发布于后端 blog.csdn.net

在单元测试中修改Bean的依赖

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

2018年08月09日 发布,来源:blog.csdn.net

基于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;

}

 

5.总结

监听器的方式解放了代码中硬编码注入mock对象,使得代码简洁干净。

730 浏览 2 收藏 报告 阅读模式
载入中...