自己在写自动化测试工具有关thrift服务自动化测试遇到的问题
首先给大家看一段代码
public static void test(List<Long> list){
System.out.println(list.get(0));
System.out.println(list.get(0) + 123);
System.out.println(list.get(0).getClass());
}
public static void bugTest1(){
String json = "[50004172,926513792]";
for(Method m :ThriftGenUtils.class.getMethods()){
if("test".equals(m.getName())){
for(Class<?> pClass : m.getParameterTypes()){
Object argCasted = Json.strToObj(json, pClass);
try {
m.invoke(new ThriftGenUtils(),argCasted);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
运行bugTest1
问题:
1 argCasted具体类型为List,其中的泛型具体类型为什么类型?为什么?
2 invoke是否能成功?
3 若invoke成功了,list的泛型具体类型是什么类型?test是否可以成功运行?若不能成功运行,到哪一行出错?报什么错误?为什么?
答案:
1 Integer,m.getParameterTypes()获取到的泛型类型是不包括具体类型的,也就是Json.strToOb调用的时候pClass只是传了List,Json转换的时候只知道是数据类型,默认转成Integer,浮点数转为Double。
2 是
3 Integer,不能成功,到+123那一行报类型转换异常Integer不能转换为Long类型,原因是泛型类型擦除。(泛型类型擦除:http://blog.csdn.net/caihaijiang/article/details/6403349 )
目前的解决方案为获取到泛型类型及具体类型,通过ObjectMapper.getTypeFactory().constructParametricType(clazz,genericClazzes)来获取javaType再来转换成Object对象
改造后,实现的相关代码如下
Method method = null;
List<Object> argList = new ArrayList<>();
for (Method m : clientClazz.getMethods()){
if(!methodName.equals(m.getName())){continue;}
method = m;
Type[] types = m.getGenericParameterTypes();
Class[] classes = m.getParameterTypes();
int i = 0;
for ( Type c: types) {
int index = i++;
String arg = args[index];
if(!(c instanceof ParameterizedType)){
String jsonStr = Json.ObjToStr(arg);
argList.add(Json.strToObj(jsonStr,classes[index]));
continue;
}
ParameterizedType pt = (ParameterizedType) c;
ObjectMapper mapper = new ObjectMapper();
Class<?>[] genericClazzes = new Class<?>[pt.getActualTypeArguments().length];
int j = 0;
for(Type type : pt.getActualTypeArguments()){
genericClazzes[j ++] = (Class) type;
}
JavaType javaType = mapper.getTypeFactory().constructParametricType(classes[index],genericClazzes);
Object argCasted = mapper.readValue(arg,javaType);
argList.add(argCasted);
}
break;
}
if ( method != null){
res = method.invoke(obj,argList.toArray());
}