利用切面进行mock测试(运用到guava的map)

package com.guahao.dap.mi.access.service.impl.utils.aspect;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.util.ParameterizedTypeImpl;
import com.google.common.collect.HashMultimap;
import com.guahao.dap.mi.access.biz.manager.cache.CodisComponent;
import com.guahao.dap.mi.access.biz.manager.facade.MockFManager;
import com.guahao.dap.mi.access.model.core.po.MockDataPO;
import com.guahao.dap.mi.access.model.core.po.MockGroupPO;
import com.guahao.dap.mi.access.model.core.po.MockGroupTargetPO;
import com.guahao.dap.mi.access.model.core.po.MockRulePO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * mock数据切面类
 *
 * @author f
 * @version V1.0
 * @since 2020/8/27 17:20
 */
@Aspect
@Component
public class ExtMockDataAspect {

    private static final Logger LOGGER = LoggerFactory.getLogger(ExtMockDataAspect.class);

    @Resource
    private MockFManager mockFManager;

    @Autowired
    protected CodisComponent codisComponent;


    @Pointcut("@annotation(com.guahao.dap.mi.access.biz.manager.annotation.DealMock)")
    public void extMockDataCut() {

    }

    @Around("extMockDataCut()")
    public Object trace(final ProceedingJoinPoint joinPoint) throws Throwable{
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Object[] args = joinPoint.getArgs();
        JSONObject param = JSONObject.parseObject(JSONObject.toJSONString(args[0]));
        LOGGER.info("切面mock接口请求数据:{}", param.toJSONString());
        //获取厂商id
        String platformId = param.getString("platformId");
        //获取匹配规则
        try {
            MockRulePO mockPO = mockFManager.getMockRule(method.getName(), platformId);
            if (mockPO != null && mockPO.getId() != null) {
                List<MockGroupPO> mockGroupPO = mockFManager.getMockGroup(mockPO.getId());
                //选出所有的组放入multiMap里面(key-value=int,list)
                HashMultimap<Integer, MockGroupPO> linkedListMultimap = HashMultimap.create();
                for (MockGroupPO m : mockGroupPO) {
                    linkedListMultimap.put(m.getFilterGroup(), m);
                }
                Integer groupId = null;
                Map<Integer, Collection<MockGroupPO>> maps = linkedListMultimap.asMap();
                //按照map的value(list)的长度降序
                LinkedHashMap<Integer, Collection<MockGroupPO>> map = maps.entrySet().stream().sorted(
                        (o1, o2) -> Integer.compare(o2.getValue().size(), o1.getValue().size()))
                             .collect(Collectors.
                                toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new));
                //迭代map,如果命中group即返回groupId
                String key;
                String[] keys;
                JSONObject jsonObject = param;
                for (Map.Entry<Integer, Collection<MockGroupPO>> me : map.entrySet()) {
                    Boolean flag = true;
                    for (MockGroupPO mo : me.getValue()) {
                        if (StringUtils.isNotBlank(mo.getFilterKey())) {
                            keys = mo.getFilterKey().split("\\.");
                            for (int i = 0, length = keys.length - 1; i < length; ++i) {
                                jsonObject = jsonObject.getJSONObject(keys[i]) == null ? new JSONObject() : jsonObject.getJSONObject(keys[i]);
                            }
                            key = jsonObject.getString(keys[keys.length - 1]) == null ? "" : jsonObject.getString(keys[keys.length - 1]);

                            if (!StringUtils.equals(key, mo.getFilterValue())) {
                                flag = false;
                            }
                        }
                        jsonObject = param;
                    }
                    if (flag) {
                        groupId = me.getKey();
                        break;
                    }
                }
                //选出mock数据
                if (groupId != null) {
                    MockGroupTargetPO mockGroupTargetPO = mockFManager.getMockGroupAndTarget(mockPO.getId(), groupId);
                    MockDataPO mockDataPO = mockFManager.getMockData(mockGroupTargetPO.getId());
                    LOGGER.info("切面mock接口返回数据:{}", mockDataPO.getData());
                    List<Type> returnType = getReturnType(method.getGenericReturnType());
                    return JSONObject.parseObject(mockDataPO.getData(), buildType(returnType));
                }
            }
        }catch (Exception e){
            Object result = joinPoint.proceed();
            LOGGER.info("切面外部接口返回数据:{}",result);
            return result;
        }
        try{
            Object result = joinPoint.proceed();
            LOGGER.info("切面外部接口返回数据:{}",result);
            return result;
        } catch (Exception e) {
            LOGGER.error("mock切面执行proceed出现异常:{}",e);
            throw e;
        }
    }

    /**
     * 递归获取全部返回类的类型值
     */
    private List<Type> getReturnType(Type genericReturnType) {
        if (genericReturnType == null) {
            return null;
        }
        Type rootType = genericReturnType;
        List<Type> typeList = new ArrayList<>();
        //获取原始返回值类型
        typeList.add(rootType);
        if (rootType instanceof ParameterizedType) {
            //获取泛型,包括泛型中的泛型
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                //判断泛型里是否有泛型
                if (actualTypeArgument instanceof ParameterizedType) {
                    typeList.addAll(getReturnType(actualTypeArgument));
                    } else {
                        typeList.add(actualTypeArgument);
                    }
            }
        }
        if (!CollectionUtils.isEmpty(typeList)) {
            return typeList;
        } else {
            return null;
        }
    }
    /**
     * 拼接返回数据类型ParameterizedTypeImpl
     * @param types
     * @return
     */
    private static Type buildType(List<Type> types) {
        ParameterizedTypeImpl beforeType = null;
        if (types != null && types.size() > 0) {
            for (int i = types.size() - 1; i > 0; i--) {
                beforeType = new ParameterizedTypeImpl(new Type[] { beforeType == null ? types.get(i) : beforeType },
                        null, types.get(i - 1));
            }
        }
        return beforeType;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要模拟Spring切面进行测试,可以使用Mockito框架来创建切面Mock对象,然后在测试使用这个Mock对象来验证切面的行为。 以下是一个简单的示例: 假设有一个名为MyAspect的切面,它有一个名为myAdvice的通知方法: ```java @Aspect public class MyAspect { @Before("execution(* com.example.service.*.*(..))") public void myAdvice() { // do something } } ``` 现在我们想要测试这个切面的行为,我们可以使用Mockito框架来创建一个MyAspect的Mock对象,并在测试中验证它的行为: ```java @RunWith(MockitoJUnitRunner.class) public class MyAspectTest { @Mock private JoinPoint joinPoint; @Mock private ProceedingJoinPoint proceedingJoinPoint; @InjectMocks private MyAspect myAspect; @Test public void testMyAdvice() throws Throwable { // create target object MyService myService = new MyService(); // create method signature MethodSignature signature = mock(MethodSignature.class); when(signature.getMethod()).thenReturn(myService.getClass().getMethod("doSomething")); // create join point joinPoint = mock(JoinPoint.class); when(joinPoint.getSignature()).thenReturn(signature); when(joinPoint.getTarget()).thenReturn(myService); // create proceeding join point proceedingJoinPoint = mock(ProceedingJoinPoint.class); when(proceedingJoinPoint.getSignature()).thenReturn(signature); when(proceedingJoinPoint.getTarget()).thenReturn(myService); when(proceedingJoinPoint.proceed()).thenReturn(null); // call advice myAspect.myAdvice(joinPoint); myAspect.myAdvice(proceedingJoinPoint); // verify behavior verify(joinPoint, times(2)).getSignature(); verify(joinPoint, times(2)).getTarget(); verify(proceedingJoinPoint, times(1)).proceed(); } } ``` 在这个测试中,我们使用Mockito创建了一个JoinPoint和ProceedingJoinPoint的Mock对象,并将它们注入到MyAspect的实例中。然后我们创建了一个MyService的实例作为目标对象,并创建了一个MethodSignature来模拟方法签名。 接下来,我们调用MyAspect的myAdvice方法,并使用创建的Mock对象来验证它的行为。在这个例子中,我们验证了getSignature和getTarget方法被调用了两次,并验证了proceedingJoinPoint.proceed方法被调用了一次。 这样,我们就可以使用Mockito框架来模拟Spring切面进行测试了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值