SpringBootTest测试框架四

dubbo调用mock

同理,为了实现dubbo的mock,也是要在dubbo调用的过程中添加拦截器

dubbo原始的执行拦截器

在这里插入图片描述

Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker))
这里代码写死了,没办法了,只能将整个JavassistProxyFactory 替换掉

public class JavassistProxyFactory extends AbstractProxyFactory {

    @Override
    @SuppressWarnings("unchecked")
    public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
        return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
    }

    @Override
    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
        // TODO Wrapper cannot handle this scenario correctly: the classname contains '$'
        final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
        return new AbstractProxyInvoker<T>(proxy, type, url) {
            @Override
            protected Object doInvoke(T proxy, String methodName,
                                      Class<?>[] parameterTypes,
                                      Object[] arguments) throws Throwable {
                return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
            }
        };
    }

}
覆盖默认代理类

在项目 \src\test\resources\META-INF\dubbo\internal下增加文件org.apache.dubbo.rpc.ProxyFactory,增加自定义代理类
localMockProxy=com.xxx.RemoteResultAdaptDubboProxyFactory

@Adaptive
public class RemoteResultAdaptDubboProxyFactory extends JavassistProxyFactory {

    @Override
    @SuppressWarnings("unchecked")
    public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
        InvokerInvocationHandler invokerInvocationHandler = new InvokerInvocationHandler(invoker);

//自定义实现拦截类
        RemoteResultInvocationHandler remoteResultInvocationHandler = new RemoteResultInvocationHandler(invokerInvocationHandler);
        //创建动态代理对象
        return (T) Proxy.getProxy(interfaces).newInstance(remoteResultInvocationHandler);


    }

    @Override
    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
        return super.getInvoker(proxy, type, url);
    }


}
自定义拦截器
public class RemoteResultInvocationHandler implements InvocationHandler {
    public static final Logger logger = LoggerFactory.getLogger(RemoteResultInvocationHandler.class);

    private InvokerInvocationHandler invokerInvocationHandler;
    private Map<String, Integer> callCountMap = Maps.newHashMap();


    public RemoteResultInvocationHandler(InvokerInvocationHandler invokerInvocationHandler) {
        this.invokerInvocationHandler = invokerInvocationHandler;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        CustMethod methodInfo = getInvokeInfo(method);
        methodInfo.name = method.getName();

        String methodName = buildFileName(methodInfo);


        Function<String, Object> mockFunction = filePath -> getMockReturnType(filePath, methodInfo.returnType);

        Function remoteFunction = s -> {
            try {
                return invokerInvocationHandler.invoke(proxy, method, args);
            } catch (Throwable e) {
                logger.error("methodName={} dubbo remote error", methodName, e);
                throw new RuntimeException(e);
            }
        };

        Object result = TestFileHelper.getResult(methodName, mockFunction, remoteFunction);

        return result;
    }


    private String buildFileName(CustMethod method) {
        String className = method.className;
        String methodName = method.name;

        String fileName = className.substring(className.lastIndexOf(".") + 1) + "_" + methodName;

        return fileName;
    }

    private CustMethod getInvokeInfo(Method method) {
        CustMethod invokeInfo = getInvokeMethodInfo(method);
        if (invokeInfo != null) {
            invokeInfo.name = method.getName();
            return invokeInfo;
        }

        invokeInfo = new CustMethod();
        invokeInfo.className = method.getDeclaringClass().getName();
        invokeInfo.name = method.getName();
        invokeInfo.returnType = method.getReturnType();
        return invokeInfo;
    }

   // fastjson 麻烦,还是建议用Gson
    public static Object getMockReturnType(String filePath, Object type) {
        String result = TestFileHelper.readFile(filePath);
        if (type == null) {
            return result;
        }
        if (type instanceof Class) {
            Class<?> aClass = (Class<?>) type;
            if (aClass.isAssignableFrom(List.class)) {
                Object object = JSONObject.parseArray(result, aClass);
                return object;
            } else {
                Object object = JSONObject.parseObject(result, aClass);
                return object;
            }
        } else if (type instanceof Type[]) {
            if (((Type[])type).length > 1) {
                Object object = JSONObject.parseObject(result, ((Type[])type)[1]);
                return object;
            }else {
                Object object = JSONObject.parseObject(result, ((Type[])type)[0], ParserConfig.global);
                return object;

            }
        }

        return result;
    }

    private CustMethod getInvokeMethodInfo(Method method) {
        try {

            CustMethod custMethod = new CustMethod();
            Object invoker = getDeclaredField(this.invokerInvocationHandler, "invoker");
            if (invoker != null) {
                Class aClass = ((MigrationInvoker) invoker).getInterface();

                ClassRepository genericInfo = (ClassRepository) getDeclaredField(aClass, "genericInfo");
                if (genericInfo != null && ArrayUtils.isNotEmpty(genericInfo.getSuperInterfaces())) {
                    Type superInterface = genericInfo.getSuperInterfaces()[0];
                    ParameterizedTypeImpl parameterizedType = (ParameterizedTypeImpl) superInterface;
                    Type actualTypeArgument = parameterizedType.getActualTypeArguments()[1];

                    custMethod.returnType = actualTypeArgument;
                    custMethod.className = aClass.getName();

                    return custMethod;
                }else {
                    String protocolServiceKey = (String) getDeclaredField(this.invokerInvocationHandler, "protocolServiceKey");

                    RpcInvocation rpcInvocation = new RpcInvocation(method, aClass.getName(), protocolServiceKey, method.getParameterTypes());
                    custMethod.returnType = rpcInvocation.getReturnTypes();
                    custMethod.className = aClass.getName();
                    return custMethod;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }



        return null;
    }


    class CustMethod {
        public String name;
        public Object returnType;
        public String className;

    }


    public static Object getDeclaredField(Object obj, String fieldName){
        try {
            Field field = obj.getClass().getDeclaredField(fieldName);
            field.setAccessible(true); // 设置访问权限,因为"name"是私有属性
            return field.get(obj); // 通过反射获得"employee"的"name"属性的值
        }catch(Exception e) {
            e.printStackTrace();
        }

        return null;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值