mock生成java對象(支持集合嵌套)



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

https://blog.csdn.net/hexingen/article/details/79355672

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章