MockIto+Spring測試抽象類中的方法

MockIto+Spring測試抽象類中的方法

使用場景:
抽象類AManager.class中的實現方法getSomeThing()的測試
由於是在SpringBoot的項目中,首先引入SpringBoot的測試註解


@RunWith(SpringRunner.class)
@SpringBootTest(classes = Bootstrap.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@DirtiesContext
public class AManagerTest{
...}

然後對getSomeThing()中的外部方法的調用和AManager類的成員變量進行Mock

//通過Mockito對抽象類進行mock
AManager aManager = Mockito.mock(AManager.class, Mockito.CALLS_REAL_METHODS);

File file = Mockito.mock(File.class);
RedisService redisServicemock = Mockito.mock(RedisService.class);
//通過反射獲取到需要替換的成員變量 f--變量名
Field testField = AManager.class.getDeclaredField("f");
testField.setAccessible(true);
testField.set(aManager, file);

通過Mockito.when(…).thenReturn(true);對mock的成員變量或者類對象的方法設置返回值

Mockito.when(file.exists()).thenReturn(true);

對抽象類中對Spring容器中託管的類對象的替換

先給出AopTargetUtils這個抽象類,來自大神的博客

package com.zm_recordUser;

import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.aop.framework.AopProxy;
import org.springframework.aop.support.AopUtils;

import java.lang.reflect.Field;

public class AopTargetUtils {

    /**
     * 獲取 目標對象
     * @param proxy 代理對象
     * @return
     * @throws Exception
     */
    public static Object getTarget(Object proxy) throws Exception {
        if(!AopUtils.isAopProxy(proxy)) {
            return proxy;//不是代理對象
        }
        if(AopUtils.isJdkDynamicProxy(proxy)) {
            return getJdkDynamicProxyTargetObject(proxy);
        } else { //cglib
            return getCglibProxyTargetObject(proxy);
        }
    }

    private static Object getCglibProxyTargetObject(Object proxy) throws Exception {
        Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");
        h.setAccessible(true);
        Object dynamicAdvisedInterceptor = h.get(proxy);
        Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");
        advised.setAccessible(true);
        return ((AdvisedSupport)advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget();
    }


    private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception {
        Field h = proxy.getClass().getSuperclass().getDeclaredField("h");
        h.setAccessible(true);
        AopProxy aopProxy = (AopProxy) h.get(proxy);
        Field advised = aopProxy.getClass().getDeclaredField("advised");
        advised.setAccessible(true);
        return ((AdvisedSupport)advised.get(aopProxy)).getTargetSource().getTarget();
    }
}

具體使用

//先對Service進行Mock,使用註解的時候需要進行init,這裏不做介紹
@Mock
XxService xxService
//或者
XxService xxService = Mockito.mock(XxService);

//以上是創建XxService的mock
//然後同樣通過when...thenReturn 對XxService的某方法的返回值進行Mock
 Mockito.when(xxService.get()).thenReturn(true);

//最後通過工具類進行Service的替換        ReflectionTestUtils.setField(AopTargetUtils.getTarget(aManager),"xxService",xxServiceMock);

具體的原理和詳細mock的內容後續再進行補充,這篇博文主要是對今天碰到的抽象類的方法的測試進行總結

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章