Mock.java - 二次封装(基于属性结构类型生成测试数据)

概述

官网: https://gitee.com/ForteScarlet/Mock.java

依赖: https://mvnrepository.com/artifact/io.gitee.ForteScarlet/mock.java

代码

二次封装

工具


EnhanceClassUtil.java

package work.linruchang.lrcutilsweb.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.BasicType;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.TypeUtil;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.util.*;

/**
 * @author LinRuChang
 * @version 1.0
 * @date 2022/10/09
 * @since 1.8
 **/
public class EnhanceClassUtil extends ClassUtil {


    /**
     * 获取数组元素的反射,非数组直接返回null
     * @param arrayClazz 数组Class
     * @return
     */
    public static Class getArrayElementClass(Class arrayClazz) {
        if(arrayClazz != null && arrayClazz.isArray()) {
            return forName(StrUtil.removeAny(arrayClazz.getName(),"[L", ";"));
        }
        return null;
    }

    /**
     * 某字段的类型是容器,获取其容器的元素类型
     * <p>
     * List<Long>  ==> Long.class
     * List ==> Object.class
     *
     * @param field
     * @return
     */
    public static Class getCollElemType(Field field) {
        Assert.notNull(field, "缺乏字段,请检查");
        Assert.isTrue(Collection.class.isAssignableFrom(field.getType()), "入参必须是容器类型的字段,请检查:{}", field);
        Type genericType = field.getGenericType();
        if (ParameterizedType.class.isAssignableFrom(genericType.getClass())) {
            return (Class) TypeUtil.getTypeArgument(genericType);
        } else {
            return Object.class;
        }
    }

    public static boolean isNumberType(Class clazz) {
        boolean result = false;
        if (clazz != null) {
            List<? extends Class<? extends Number>> numberClasses = Arrays.asList(Byte.class, Byte.TYPE, Short.class, Short.TYPE, Integer.class, Integer.TYPE, Long.class, Long.TYPE, BigInteger.class, Float.class, Float.TYPE, Double.class,Double.TYPE);
            if (CollUtil.contains(numberClasses, clazz)) {
                result = true;
            } else {
                // TODO
            }
        }
        return result;
    }

    public static boolean isDateType(Class clazz) {
        boolean result = false;
        if (clazz != null) {
            List<Class> dateClasses = Arrays.asList(Date.class, Calendar.class, LocalDate.class, LocalDateTime.class, ZonedDateTime.class,java.sql.Date.class);
            if (CollUtil.contains(dateClasses, clazz)) {
                result = true;
            } else {
                // TODO
            }
        }
        return result;
    }


    /**
     * 获取基本变量类型,找不到直接返回null
     * @param type 基本变量类型全限定名
     * @return
     */
    public static Class getBasicType(String type) {
        return BasicType.WRAPPER_PRIMITIVE_MAP.values().stream()
                .filter(clazz -> StrUtil.equals(type, clazz.getName()))
                .findFirst()
                .orElse(null);
    }

    /**
     * 获取类型,找不到不抛异常直接返回null
     *
     * 支持基本类型反射获取
     * @param type 类型的全限定名
     * @return
     */
    public static Class getType(String type) {
        return ObjectUtil.defaultIfNull(forName(type), getBasicType(type));
    }

    /**
     * 获取所有父类,不含Object.class
     * @param clazz 反射
     * @return
     */
    public static List<Class> superClasses(Class clazz) {
        List<Class> result = CollUtil.newArrayList();
        if (clazz != null) {
            while (true) {
                clazz = clazz.getSuperclass();
                if (clazz == Object.class) {
                    break;
                }
                result.add(clazz);
            }
        }
        return result;
    }

    /**
     * 获取JDK类型,如果类型非jdk,直接返回null
     *
     * @param type 类型全限定名
     * @return
     */
    public static Class getJdkClass(String type) {
        Class result = getBasicType(type);
        if (result == null) {
            result = forName(type);
            result = isJdkClass2(result) ? result : null;
        }
        return result;
    }

    /**
     * 是否是JDK定义的类型
     * @param clazz
     * @return
     */
    public static boolean isJdkClass2(Class clazz) {
        if (clazz == null) {
            return false;
        }
        boolean javaFlag = StrUtil.startWithAny(clazz.getName(), "java.", "[Ljava.");
        if (!javaFlag) {
            return superClasses(clazz).stream()
                    .anyMatch(superClazz -> StrUtil.startWithAny(superClazz.getName(), "java.", "[Ljava."));
        }
        return javaFlag;
    }

    /**
     * 获取Class实例 == 获取不到不会抛出异常
     * @param type 类全限定名
     * @return
     */
    public static Class forName(String type) {
        try {
            return Class.forName(type);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 是否【是】普通字段的类型
     * @param type 类型全限定名
     * @return
     */
    public static boolean isBeanFieldJavaType(String type) {
        return getJdkClass(type) != null;
    }

    /**
     * 是否【不是】普通字段的类型
     * @param type 类型全限定名
     * @return
     */
    public static boolean isNotBeanFieldJavaType(String type) {
        return !isBeanFieldJavaType(type);
    }
}


EnhanceRandomUtil.java

package work.linruchang.lrcutilsweb.util;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.RandomUtil;
import com.forte.util.utils.MockUtil;

/**
 * 增强的随机工具类
 *
 * @author LinRuChang
 * @version 1.0
 * @date 2022/10/09
 * @since 1.8
 **/
public class EnhanceRandomUtil extends RandomUtil {


    public static Object[] nums(Class numberType, Integer numCount) {
        Object[] randomNumsResult = new Object[numCount];
        for (int index = 0; index < numCount; index++) {
            randomNumsResult[index] = Convert.convert(numberType, randomLong());
        }
        return randomNumsResult;
    }

    public static Object[] dates(Class numberType, Integer dateCount) {
        Object[] datesResult = new Object[dateCount];
        for(int index = 0; index < dateCount; index++) {
            datesResult[index]  = Convert.convert(numberType, MockUtil.date());
        }
        return datesResult;
    }

    public static Boolean[] bools(Integer booleanCount) {
        Boolean[] result = new Boolean[booleanCount];
        for(int index = 0; index < booleanCount; index++) {
            result[index] = randomBoolean();
        }
        return result;
    }

    public static Character[] characters(Integer charactersCount) {
        Character[] result = new Character[charactersCount];
        for(int index = 0; index < charactersCount; index++) {
            result[index] = MockUtil.character();
        }
        return result;
    }
}


EnhanceMockUtil.java

package work.linruchang.lrcutilsweb.util;

import cn.hutool.core.convert.BasicType;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReflectUtil;
import com.forte.util.Mock;
import com.forte.util.loader.MethodLoader;
import com.forte.util.mockbean.MockMapBean;
import com.forte.util.utils.MockUtil;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * 增强的{@link MockUtil}
 *
 * @author LinRuChang
 * @version 1.0
 * @date 2022/10/08
 * @since 1.8
 **/
public class EnhanceMockUtil {


    private static Object mockRandomData(String dateType) {
        Class aClass = EnhanceClassUtil.getJdkClass(dateType);
        if (aClass == null) {
            return null;
        }

        boolean isArrayFlag = aClass.isArray();
        Integer arrayElemeCount = RandomUtil.randomInt(1, 10);
        Object[] result = new Object[0];


        // 数组类型
        if (isArrayFlag) {
            aClass = BasicType.wrap(EnhanceClassUtil.getArrayElementClass(aClass));
        } else { // 普通类型
            aClass = BasicType.wrap(aClass);
        }

        //不会有基本类型
        Class elementClass = aClass;

        if (aClass == String.class) {
            result = MockUtil.names(arrayElemeCount);
        } else if (EnhanceClassUtil.isNumberType(aClass)) {
            result = EnhanceRandomUtil.nums(aClass, arrayElemeCount);
        }else if(aClass == Boolean.class) {
            result = EnhanceRandomUtil.bools(arrayElemeCount);
        }else if(EnhanceClassUtil.isDateType(aClass)) {
            result = EnhanceRandomUtil.dates(aClass,arrayElemeCount);
        }else if (aClass == Character.class) {
            result = EnhanceRandomUtil.characters(arrayElemeCount);
        }


        return isArrayFlag?result:EnhanceArrayUtil.getFirst(result);
    }


    /**
     * mock数据生成
     *
     * @param dateType    mock的数据类型
     * @param proertyName mock的字段名
     * @return
     */
    public static Object mockData(String dateType, String proertyName) {
        Class dateTypeClazz = EnhanceClassUtil.getJdkClass(dateType);
        if (dateTypeClazz != null) {
            // 不支持容器类型转换
            if (Collection.class.isAssignableFrom(dateTypeClazz)) {
                return Collections.emptyList();
            } else  {
                return mockRandomData(dateType);
            }
        } else {
            return null;
        }
    }


    public static void main(String[] args) {

        MethodLoader methodLoader = Mock.mockMethodLoader();
        methodLoader.append(ReflectUtil.getMethod(EnhanceMockUtil.class, "testMock"));
        methodLoader.append(ReflectUtil.getMethod(EnhanceMockUtil.class, "mockData", String.class, String.class));
        methodLoader.load();


        Map<String, Object> ruleMap = new HashMap<>();
        ruleMap.put("age1", "@age");
        ruleMap.put("age2", 15);
        ruleMap.put("age3", new Integer[]{1, 2, 3, 4});
        ruleMap.put("name1", "@name");
        ruleMap.put("name2", "@title(2)");
        ruleMap.put("name3", "这是一个名字");

        ruleMap.put("email1", "@email('这是中文')");
        ruleMap.put("email2", "@email('this is english')");
        ruleMap.put("email3", "@email(this is english)");
        ruleMap.put("testMock", "@testMock");
        ruleMap.put("mockData", "@mockData('fdsfds','fdsfdsf5345')");
        // ruleMap.put("email4" , null);

        MockMapBean test = Mock.setResult("test", ruleMap, false);

        test.getObject().entrySet()
                .forEach(Console::log);


    }


}


MyMockUtil.java

package work.linruchang.lrcutilsweb.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.forte.util.Mock;
import com.forte.util.loader.MethodLoader;
import com.forte.util.mockbean.MockMapBean;

import java.util.HashMap;
import java.util.Map;

/**
 * @author LinRuChang
 * @version 1.0
 * @date 2022/10/08
 * @since 1.8
 **/
public class MyMockUtil {

    static {
        MethodLoader methodLoader = Mock.mockMethodLoader();
        methodLoader.append(ReflectUtil.getMethod(EnhanceMockUtil.class, "mockData", String.class, String.class));
        methodLoader.load();
    }


    public static Map<String,Object> mockResult(Map<String, Object> ruleMap) {
        MockMapBean test = Mock.setResult(UUID.fastUUID().toString(true), ruleMap, false);
        return test.getObject();
    }

    public static String mockResultJson(Map<String, Object> ruleMap) {
        return JSONUtil.toJsonStr(mockResult(ruleMap));
    }

    public static Map<String, Object> generateRuleMap(Map<String, Object> beanFieldStructure) {
        HashMap<String, Object> copyMap = MapUtil.newHashMap();
        BeanUtil.copyProperties(beanFieldStructure, copyMap);
        return generateRuleMapByLoop(copyMap);
    }

    /**
     * 基于结构生成mock规则
     *
     * @param beanFieldStructure Bean结构
     * @return
     */
    private static Map<String, Object> generateRuleMapByLoop(Map<String, Object> beanFieldStructure) {
        MapUtil.emptyIfNull(beanFieldStructure).forEach((properName, properType) -> {
            if(properType != null) {
                if(properType instanceof Class) {
                    beanFieldStructure.put(properName, StrUtil.format("@mockData('{}','{}')", ((Class<?>) properType).getName(), properName));
                }else {
                    generateRuleMapByLoop((Map<String, Object>) properType);
                }
            }else {
                beanFieldStructure.put(properName, StrUtil.format("@mockData('{}','{}')", null, properName));
            }
        });
        return beanFieldStructure;
    }




}

测试
    @Test
    public void testGenerateRuleMap3() {

        Map<String,Object> map = new HashMap<>();

        map.put("name", "@name");


        Map<String,Object> infoMap = new HashMap<>();
        infoMap.put("year", "@UUNUM");
        map.put("info", infoMap);
        map.put("aa", "@mockData('long','aa')");
        map.put("bb", StrUtil.format("@mockData('{}','{}')", String[].class.getName(),"bb"));

        String s = MyMockUtil.mockResultJson(map);

        Console.log(JSONUtil.formatJsonStr(s));

    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mxu3Skie-1665315898381)(en-resource://database/62398:1)]

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值