import org.reflections.ReflectionUtils;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
/**
* 描述:mock对象
* 注意:
* 1、StackOverflow异常,一般是由于尝试mock自包含的类,比如菜单树
* 2、暂时不支持Map中的key为Set或者List或者Map类型
*
* @author jianlin.zhu
* @create 2019-11-05 11:25
**/
public class MockUtil {
private static final Boolean[] bools = new Boolean[] { true, false };
private static final char[] words = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
private static final Random r = new Random();
private static final int MAX_COLLECTION_LENGTH = 3;
private static final int MAX_STRING_LENGTH = 15;
@SuppressWarnings({ "unchecked", "rawtypes" })
public static <T> T mock(Class<T> clazz) {
if (clazz == Character.class || clazz == Character.TYPE) {
return (T) (Character) words[r.nextInt(words.length)];
} else if (clazz == Boolean.class || clazz == Boolean.TYPE) {
return (T) (Boolean) bools[r.nextInt(bools.length)];
} else if (clazz == Long.class || clazz == Long.TYPE) {
return (T) (Long) r.nextLong();
} else if (clazz == Integer.class || clazz == Integer.TYPE) {
return (T) (Integer) r.nextInt();
} else if (clazz == Short.class || clazz == Short.TYPE) {
return (T) (Short) new Integer(r.nextInt(127)).shortValue();
} else if (clazz == Float.class || clazz == Float.TYPE) {
return (T) (Float) r.nextFloat();
} else if (clazz == Double.class || clazz == Double.TYPE) {
return (T) (Double) r.nextDouble();
} else if (clazz == String.class) {
return (T) randString(r.nextInt(MAX_STRING_LENGTH));
}
try {
T instance = clazz.newInstance();
for (Field f : ReflectionUtils.getAllFields(clazz)) {// getAllFields 返回本类和超类全部字段,getFields仅返回当前类成员
f.setAccessible(true);
field长度
if (f.getType() == Character.TYPE) {
f.setChar(instance, words[r.nextInt(words.length)]);
} else if (f.getType() == Character.class) {
f.set(instance, words[r.nextInt(words.length)]);
} else if (f.getType() == Boolean.TYPE) {
f.setBoolean(instance, bools[r.nextInt(bools.length)]);
} else if (f.getType() == Boolean.class) {
f.set(instance, bools[r.nextInt(bools.length)]);
} else if (f.getType() == Long.TYPE) {
f.setLong(instance, r.nextLong());
} else if (f.getType() == Long.class) {
f.set(instance, r.nextLong());
} else if (f.getType() == Integer.TYPE) {
f.setInt(instance, r.nextInt());
} else if (f.getType() == Integer.class) {
f.set(instance, r.nextInt());
} else if (f.getType() == Short.TYPE) {
f.setShort(instance, new Integer(r.nextInt(127)).shortValue());
} else if (f.getType() == Short.class) {
f.set(instance, new Integer(r.nextInt(127)).shortValue());
} else if (f.getType() == Float.TYPE) {
f.setFloat(instance, r.nextFloat());
} else if (f.getType() == Float.class) {
f.set(instance, r.nextFloat());
} else if (f.getType() == Double.TYPE) {
f.setDouble(instance, r.nextDouble());
} else if (f.getType() == Double.class) {
f.set(instance, r.nextDouble());
} else if (f.getType() == String.class) {
f.set(instance, randString(r.nextInt(MAX_STRING_LENGTH)));
} else if (f.getType() == List.class) {
f.set(instance, generateList((ParameterizedType)f.getGenericType()));
}else if (f.getType() == Set.class) {
f.set(instance, generateSet((ParameterizedType)f.getGenericType()));
} else if (f.getType() == Map.class) {
ParameterizedType pt = (ParameterizedType) f.getGenericType();
f.set(instance, generateMap(pt));
} else if (f.getType() == Date.class) {
f.set(instance, new Date());
} else if (f.getType().isArray()) {// 处理数组
f.set(instance, generateArray( f.getType()));
}else {
f.set(instance, mock(f.getType()));
}
}
return instance;
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
private static Map<Object, Object> generateMap( ParameterizedType pt) {
Map<Object, Object> map = new HashMap<>();
int size = r.nextInt(MAX_COLLECTION_LENGTH)+1;
for (int i = 0; i < size; i++) {
Object key = null,value = null;
//生成key,假设key不可能为List或者Map
if(pt.getActualTypeArguments()[0] instanceof Class){
key = mock((Class) pt.getActualTypeArguments()[0]);
}else{
throw new IllegalArgumentException("not supported key type:"+pt.getActualTypeArguments()[0].getTypeName());
}
// 生成value
if(pt.getActualTypeArguments()[1] instanceof Class){
value = mock((Class) pt.getActualTypeArguments()[1]);
}else if(pt.getActualTypeArguments()[1] instanceof ParameterizedType){
ParameterizedType ptype = (ParameterizedType) pt.getActualTypeArguments()[1];
if(ptype.getRawType() == List.class){
List<Object> list = generateList(ptype);
value = list;
}else if(ptype.getRawType() == Map.class){
value = generateMap((ParameterizedType) ptype.getRawType());
}else if(ptype.getRawType() == Set.class){
value = generateSet(ptype);
}
}else{
throw new IllegalArgumentException("not supported value type:"+pt.getActualTypeArguments()[1].getTypeName());
}
// 给map赋值
map.put(key, value);
}
return map;
}
private static Object[] generateArray(Class f) {
int sizeInner = r.nextInt(MAX_COLLECTION_LENGTH)+1;
Object[] objects = (Object[]) Array.newInstance(f.getComponentType(),sizeInner);
for (int i=0;i<objects.length;++i) {
objects[i] = mock(f.getComponentType());
}
return objects;
}
private static List<Object> generateList(ParameterizedType f) {
int sizeInner = r.nextInt(MAX_COLLECTION_LENGTH)+1;
List<Object> list = new ArrayList<Object>(sizeInner);
ParameterizedType ptInner = f;
for (int ii = 0; ii < sizeInner; ii++) {
if (ptInner.getActualTypeArguments()[0] instanceof Class) {
list.add(mock((Class) ptInner.getActualTypeArguments()[0]));
} else if (ptInner.getActualTypeArguments()[0] instanceof ParameterizedType) {
ParameterizedType ptype = (ParameterizedType) ptInner.getActualTypeArguments()[0];
if(ptype.getRawType() == List.class){
List<Object> obj = generateList(ptype);
list.add(obj);
}else if(ptype.getRawType() == Map.class){
list.add(generateMap(ptype));
}else if(ptype.getRawType() == Set.class){
list.add(generateSet(ptype));
}else {
throw new IllegalArgumentException("not supported type:"+ptype.getTypeName());
}
}
}
return list;
}
private static Set<Object> generateSet(ParameterizedType f) {
int sizeInner = r.nextInt(MAX_COLLECTION_LENGTH)+1;
Set<Object> set = new HashSet<>(sizeInner);
ParameterizedType ptInner = f;
for (int ii = 0; ii < sizeInner; ii++) {
if (ptInner.getActualTypeArguments()[0] instanceof Class) {
set.add(mock((Class) ptInner.getActualTypeArguments()[0]));
} else if (ptInner.getActualTypeArguments()[0] instanceof ParameterizedType) {
ParameterizedType ptype = (ParameterizedType) ptInner.getActualTypeArguments()[0];
if(ptype.getRawType() == List.class){
set.add( generateList(ptype));
}else if(ptype.getRawType() == Map.class){
set.add(generateMap(ptype));
}else if(ptype.getRawType() == Set.class){
set.add(generateSet(ptype));
}else {
throw new IllegalArgumentException("not supported type:"+ptype.getTypeName());
}
}
}
return set;
}
private static String randString(int count) {
if (count == 0) {
count = 1;
}
int length = words.length;
char[] text = new char[count];
for (int i = 0; i < count; i++) {
text[i] = words[r.nextInt(length)];
}
return new String(text);
}
}
测试case
import lombok.Data;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 描述:
*
* @author jianlin.zhu
* @create 2019-11-05 16:33
**/
@Data
public class Person {
private Long id;
private String name;
private Date birth;
private List<Set<Address>> addressList;
private Favor[] favors;
private List<Order> orderList;
private Set<Map<String,List<Set<Favor>>>> favorSet;
@Data
public static class Favor{
private String title;
private String describe;
private double score;
}
@Data
public static class Address{
private String country;
private String province;
private String city;
private String street;
private String contract;
private String phone;
private Boolean isDefault;
}
@Data
public static class Order{
private Double totalPrice;
private Address address;
private Map<Long,List<Favor>> goodsFavor;
private List<SubOrder> subOrders;
}
@Data
public static class SubOrder{
private Long goodId;
private Double salePrice;
private Double originalPrice;
private float benefit;
private String title;
}
}
import com.alibaba.fastjson.JSONObject;
/**
* 描述:
*
* @author jianlin.zhu
* @create 2019-11-05 15:34
**/
public class MockUtilTest {
public static void main(String[] args){
Person person = MockUtil.mock(Person.class);
System.out.println(JSONObject.toJSONString(person,true));
}
}
输出:
{
"addressList":[
[{
"city":"tpy",
"contract":"dpmkqimffy",
"country":"ubt",
"isDefault":true,
"phone":"yiykfamdydmsqb",
"province":"yjh",
"street":"lhbypp"
},{
"city":"kifyy",
"contract":"vofaxshgqvyqan",
"country":"bquuqw",
"isDefault":false,
"phone":"aawrrcwetiyfma",
"province":"ewnvbahrh",
"street":"saxkvomlzd"
},{
"city":"b",
"contract":"utzj",
"country":"tp",
"isDefault":false,
"phone":"wljlhuq",
"province":"gqa",
"street":"e"
}],
[{
"city":"vtlyiururjzz",
"contract":"j",
"country":"jvqoq",
"isDefault":false,
"phone":"anhtftdmenvbzr",
"province":"t",
"street":"fjsie"
}],
[{
"city":"nyjgbsd",
"contract":"u",
"country":"hbte",
"isDefault":true,
"phone":"qki",
"province":"jzyxiulfcxhen",
"street":"tzgieshs"
}]
],
"birth":1572952177324,
"favorSet":[{
"mdkzowbaiqakn":[
[{
"describe":"e",
"score":0.33512498126200196,
"title":"znmqsbv"
},{
"describe":"exrqliayt",
"score":0.12957477455951116,
"title":"v"
}],
[{
"describe":"vmqvruep",
"score":0.683872055817606,
"title":"fidlau"
},{
"describe":"teztqfps",
"score":0.8187798858446599,
"title":"k"
},{
"describe":"jhhhnbxcxr",
"score":0.3977010007177091,
"title":"pubvbtkouch"
}],
[{
"describe":"zrhoe",
"score":0.3080511445840518,
"title":"lh"
},{
"describe":"y",
"score":0.4601439044338964,
"title":"vonwufve"
}]
],
"bdhym":[
[{
"describe":"ajf",
"score":0.09017641017885825,
"title":"q"
},{
"describe":"gcfpryvijftwnh",
"score":0.3630178607696227,
"title":"q"
},{
"describe":"i",
"score":0.2649214029318562,
"title":"dqhfigmcy"
}],
[{
"describe":"pf",
"score":0.08199816360236223,
"title":"idwfkuykl"
},{
"describe":"mkibroz",
"score":0.30136369114027095,
"title":"ynfghdzudtyf"
}]
]
},{
"r":[
[{
"describe":"fhlwiznpi",
"score":0.36563747375982836,
"title":"cfevfjl"
},{
"describe":"tzkbvttinhgte",
"score":0.3904462585509223,
"title":"ig"
}],
[{
"describe":"bgdlcvlimf",
"score":0.7455985339369536,
"title":"pewbslviq"
},{
"describe":"mrlwcxnx",
"score":0.12461240816408914,
"title":"wmyamocfhlrd"
},{
"describe":"mhocivyk",
"score":0.8834363617313298,
"title":"cnyslmne"
}]
],
"us":[
[{
"describe":"wxvryqej",
"score":0.2748961395007401,
"title":"u"
},{
"describe":"cbzbcogiylecvt",
"score":0.4711109057074666,
"title":"jwecatawnhde"
}]
]
},{
"qffrbrnr":[
[{
"describe":"ybcopufhpep",
"score":0.43450414896786926,
"title":"xzl"
}]
],
"ahlgptw":[
[{
"describe":"zlqc",
"score":0.17386372799530847,
"title":"k"
},{
"describe":"jv",
"score":0.9977639709707106,
"title":"hqficilftsbf"
},{
"describe":"ehhlkpirtapys",
"score":0.9750584197570653,
"title":"rottraq"
}],
[{
"describe":"wak",
"score":0.4156394594053854,
"title":"lozvmtztpezru"
},{
"describe":"bvquwxuomayzc",
"score":0.2989801382638073,
"title":"k"
}]
],
"ojnhettqcr":[
[{
"describe":"uubwgkzuug",
"score":0.47959497074873303,
"title":"cxdgcqq"
}]
]
}],
"favors":[{
"describe":"kbdea",
"score":0.27751810255617315,
"title":"wmqhyxquev"
},{
"describe":"btilnrkqwqsyz",
"score":0.1762719693155328,
"title":"x"
},{
"describe":"h",
"score":0.7253306812757867,
"title":"bidbtih"
}],
"id":-8110089797562012842,
"name":"drioyjnq",
"orderList":[
{
"address":{
"city":"mepkyfwsi",
"contract":"d",
"country":"ycaotih",
"isDefault":true,
"phone":"fft",
"province":"b",
"street":"gxavrmsrsms"
},
"goodsFavor":{1169207484603786370:[
{
"describe":"ou",
"score":0.8277121621050381,
"title":"ttcitrr"
},
{
"describe":"ovzs",
"score":0.03187424071317824,
"title":"jflhyky"
}
],8152713560997322139:[
{
"describe":"inuvfodmyb",
"score":0.4988076295011178,
"title":"xqiwxwlzqzuhc"
},
{
"describe":"xnhgxhy",
"score":0.11535246421995216,
"title":"jbjpfvxpeuyrbw"
}
]
},
"subOrders":[
{
"benefit":0.6409404,
"goodId":-2489116054044592929,
"originalPrice":0.7165577881107803,
"salePrice":0.7082018344414069,
"title":"osyokfadesgp"
}
],
"totalPrice":0.6517598699982142
}
]
}
参考资料:
https://blog.csdn.net/xupeng874395012/article/details/61205434