自己在寫自動化測試工具有關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());
}