單元測試數據構造工具及單元測試抽象父類

調用newData方法,傳入指定BeanClass類型,自動根據set方法構建隨機數據,注意,這裏的set方法是指屬性的set方法,繼承的屬性也可以!具體用法參見代碼的main方法。

注意:由於部分數據進行了限制,尤其是你主鍵是int類型時,爲了避免主鍵衝突,請在單元測試類上加上回滾的註解

@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
@Transactional

或者你的 單元測試 繼承此類,注意配置文件的路徑

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:/spring-application.xml"})
@TransactionConfiguration(defaultRollback = true)
@Transactional
public class TestBaseService extends AbstractTransactionalJUnit4SpringContextTests {
    public TestBaseService() {
    }
}

import com.alibaba.fastjson.JSON;
import java.lang.reflect.*;
import java.util.*;
/**
 * 數據構造工具
 * 注意:Model中不要嵌套相同的Model,也不能互相嵌套
 * @author Yangzhen
 * @Description
 * @date 2019-09-02 15:55
 **/
public class DataBuilder {

    public static final String SAMPLE_CODE = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

    public static final Map<String, Class<?>> BASIC_DATA_TYPE_MAP = new HashMap<>();

    static {
        BASIC_DATA_TYPE_MAP.put("int", Integer.class);
        BASIC_DATA_TYPE_MAP.put("double", Double.class);
        BASIC_DATA_TYPE_MAP.put("long", Long.class);
        BASIC_DATA_TYPE_MAP.put("short", Short.class);
        BASIC_DATA_TYPE_MAP.put("byte", Byte.class);
        BASIC_DATA_TYPE_MAP.put("boolean", Boolean.class);
        BASIC_DATA_TYPE_MAP.put("char", Character.class);
        BASIC_DATA_TYPE_MAP.put("float", Float.class);
    }

    /**
     * 隨機字符串
     *
     * @param length
     * @return
     */
    public static String getRandomString(int length) {
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(SAMPLE_CODE.length());
            sb.append(SAMPLE_CODE.charAt(number));
        }
        return sb.toString();
    }

    public static Date getNow() {
        return new Date();
    }

    /**
     * 隨機數字,轉換成對應的包裝類型,對於Boolean類型的數據,總是返回false
     *
     * @param length
     * @param clazz
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> T getRandomNumber(int length, Class<?> clazz) throws Exception {

        if (length <= 0) {
            length = 1;
        }

        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        while (sb.length() < length) {
            sb.append(random.nextInt(10));
        }
        String str = sb.toString();
        if (clazz.isPrimitive()) {
            clazz = BASIC_DATA_TYPE_MAP.get(clazz.getName());
        }
        Constructor<?> constructor = clazz.getConstructor(String.class);
        Object result = constructor.newInstance(str);
        return (T) result;
    }

    /**
     * 構造數據,你的對象一定要有無參構造函數
     * 集合和Map的數據自己構建
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T newDataByMethod(Class<?> clazz) {
        try {
            Object obj = clazz.newInstance();
            Method[] methods = clazz.getMethods();
            for (Method method : methods) {
                if (method.getName().startsWith("set")) {
                    Class<?>[] parameterTypes = method.getParameterTypes();
                    Class<?> type = parameterTypes[0];
                    method.invoke(obj, getDataByClass(type));
                }
            }
            return (T) obj;
        } catch (Exception e) {
            e.printStackTrace();
            throw new IllegalArgumentException();
        }
    }

    /**
     * 構造數據,你的對象一定要有無參構造函數
     * 集合和Map的數據不需要自己構建
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T newDataByField(Class<?> clazz) {
        try {

            Object obj = clazz.newInstance();
            for (; !clazz.equals(Object.class); clazz = clazz.getSuperclass()) {
                Field[] declaredFields = clazz.getDeclaredFields();
                for (Field declaredField : declaredFields) {
                    declaredField.setAccessible(true);
                    if (Modifier.isFinal(declaredField.getModifiers()) && Modifier.isStatic(declaredField.getModifiers())) {
                        continue;
                    }
                    try {
                        method = clazz.getMethod("set" + firstToUpperCase(declaredField.getName()), declaredField.getType());
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                        continue;
                    }
                    method.invoke(obj, getDataByField(declaredField));
                }
            }
            return (T) obj;
        } catch (Exception e) {
            e.printStackTrace();
            throw new IllegalArgumentException();
        }
    }

    public static <T> T getDataByField(Field field) throws Exception {
        Class<?> clazz = field.getType();
        if (isPrimitive(clazz)) {
            return getRandomNumber(0, clazz);
        } else if (Date.class.isAssignableFrom(clazz)) {
            return (T) getNow();
        } else if (String.class.isAssignableFrom(clazz)) {
            return (T) getRandomString(6);
        } else if (clazz.isInterface()) {
            if (List.class.isAssignableFrom(clazz)) {
                // 返回的集合不能添加數據
                // return (T) Collections.emptyList();
                List<T> result = new ArrayList<>();
                genericDeal(field, result, false);
                return (T) result;
            } else if (Set.class.isAssignableFrom(clazz)) {
                Set<T> result = new HashSet<>();
                genericDeal(field, result, false);

                return (T) result;
            } else if (Map.class.isAssignableFrom(clazz)) {
                // 返回的集合不能添加數據
                // return (T) Collections.EMPTY_MAP;
                HashMap result = new HashMap<>();
                genericDeal(field, result, true);
                return (T) result;
            }
            return null;
        } else {
            // Object
            return (T) clazz.newInstance();
        }
    }

    public static void genericDeal(Field field, Object obj, boolean flag) throws Exception {
        Type genericType = field.getGenericType();
        if (genericType instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) genericType;
            if (flag) {
                Class actualType1 = (Class) parameterizedType.getActualTypeArguments()[0];
                Class actualType2 = (Class) parameterizedType.getActualTypeArguments()[1];
                Map result = (Map) obj;
                result.put(getDataByClass(actualType1), getDataByClass(actualType2));
            } else {
                Class actualType = (Class) parameterizedType.getActualTypeArguments()[0];
                Collection result = (Collection) obj;
                result.add(getDataByClass(actualType));
            }
        }
    }


    /**
     * 適配數據類型,數組類型直接返回數組對象
     *
     * @param clazz
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> T getDataByClass(Class<?> clazz) throws Exception {

        if (isPrimitive(clazz)) {
            return getRandomNumber(0, clazz);
        } else if (Date.class.isAssignableFrom(clazz)) {
            return (T) getNow();
        } else if (String.class.isAssignableFrom(clazz)) {
            return (T) getRandomString(6);
        } else if (clazz.isInterface()) {
            if (List.class.isAssignableFrom(clazz)) {
                // 返回的集合不能添加數據
                // return (T) Collections.emptyList();
                return (T) new ArrayList<>();
            } else if (Set.class.isAssignableFrom(clazz)) {
                return (T) new HashSet<>();
            } else if (Map.class.isAssignableFrom(clazz)) {
                // 返回的集合不能添加數據
                // return (T) Collections.EMPTY_MAP;
                return (T) new HashMap<>();
            }
            return null;
        } else {
            // Object
            return (T) clazz.newInstance();
        }
    }

    /**
     * 判斷基本數據類型和包裝類型
     *
     * @param clazz
     * @return
     */
    public static boolean isPrimitive(Class<?> clazz) {
        try {
            // 判斷基本數據類型
            if (clazz.isPrimitive()) {
                return true;
            }
            // 判斷包裝類型
            if (clazz.getField("TYPE") != null && ((Class) (clazz.getField("TYPE").get(null))).isPrimitive()) {
                return true;
            }
        } catch (Exception e) {
        }
        return false;
    }

    private static String firstToUpperCase(String str) {
        // 進行字母的ascii編碼前移,效率要高於截取字符串進行轉換的操作
        char[] cs = str.toCharArray();
        cs[0] -= 32;
        return String.valueOf(cs);
    }
    
	/**
     * @param clazz
     * @param prefix 前綴
     */
    public static void getFormData(Class clazz, String prefix) {

        Object o = DataBuilder.newDataByField(clazz);
        String data = JSON.toJSONStringWithDateFormat(o, "yyyy-MM-dd HH:mm:ss");

        prefix = prefix == null ? "" : prefix;
        String[] datas = data.replace("{", "").replace("}", "").replace("\"", "").split(",");

        StringBuilder sb = new StringBuilder();
        for (String str : datas) {
            sb.append(prefix).append(str).append("\n");
        }
        System.out.println(sb.toString());
    }

    public static void main(String[] args) throws Exception {
        Goods goods = newDataByField(Goods.class);
        System.out.println(JSON.toJSONString(goods));
        Fruit fruit = newDataByField(Fruit.class);
        System.out.println(JSON.toJSONString(fruit));
    }

    static class Goods {

        public Goods() {
        }

        private String name;
        private Integer count;
        private Double price;
        private List<String> ext;
        private Byte byt;
        private Boolean flag;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Integer getCount() {
            return count;
        }

        public void setCount(Integer count) {
            this.count = count;
        }

        public Double getPrice() {
            return price;
        }

        public void setPrice(Double price) {
            this.price = price;
        }

        public List<String> getExt() {
            return ext;
        }

        public void setExt(List<String> ext) {
            this.ext = ext;
        }

        public Byte getByt() {
            return byt;
        }

        public void setByt(Byte byt) {
            this.byt = byt;
        }

        public Boolean getFlag() {
            return flag;
        }

        public void setFlag(Boolean flag) {
            this.flag = flag;
        }

    }

    static class Fruit extends Goods {
        private Date date;
        private Set<String> set;
        private Map<Integer, String> map;

        public Date getDate() {
            return date;
        }

        public void setDate(Date date) {
            this.date = date;
        }

        public Map<Integer, String> getMap() {
            return map;
        }

        public void setMap(Map<Integer, String> map) {
            this.map = map;
        }

        public Set<String> getSet() {
            return set;
        }

        public void setSet(Set<String> set) {
            this.set = set;
        }
    }
}

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