Giter VIP home page Giter VIP logo

jmockdata's Introduction

github star

Jmockdata

Build Status Coverage Status Maven central License

Jmockdata是一款实现模拟JAVA类型或对象的实例化并随机初始化对象的数据的工具框架。

mark

The plugin of Jmockdata what through random algorithm mock java data.
Jmockdata插件通过随机算法模拟Java数据.

mark

Feature

  • 支持丰富多样的数据类型模拟,包括:Java基本类型、字符串、枚举、日期、数组、多维数组、集合[List|Set|Map]、枚举、Java对象等
  • 支持通过正则表达式反向模拟数据
  • 支持泛型
  • 支持继承
  • 支持循环依赖、自依赖(手动开启enabledCircle)
  • 支持忽略字段
  • 支持改变mockConfig来自定义模拟数据策略
  • 支持自定义Mocker类扩展数据模拟类型
  • 支持添加BeanMocker拦截器类改变模拟行为
  • 支持JDK1.8+

Download

Jmockdata-4.3.0

Jar

Jmockdata-4.3.0

Maven

  <dependency>
     <groupId>com.github.jsonzou</groupId>
     <artifactId>jmockdata</artifactId>
     <version>4.3.0</version>
   </dependency>

Gradle

  compile group: 'com.github.jsonzou', name: 'jmockdata', version: '4.3.0'

更多已发布版本下载

https://github.com/jsonzou/jmockdata/releases

History version

Usage

基础类型

支持以下基础类型直接模拟

描述 类型
基础类型 byte boolean char short int long float double
包装类型包装 Byte Boolean Character Short Integer Long Float Double
常用类型 BigDecimal BigInteger Date LocalDateTime LocalDate LocalTime java.sql.Timestamp String Enum
多维数组 以上所有类型的多维数组 如:int[] int[][] int[][][] .... etc.
//基本类型模拟
int intNum = JMockData.mock(int.class);
int[] intArray = JMockData.mock(int[].class);
Integer integer = JMockData.mock(Integer.class);
Integer[] integerArray = JMockData.mock(Integer[].class);
//常用类型模拟
BigDecimal bigDecimal = JMockData.mock(BigDecimal.class);
BigInteger bigInteger = JMockData.mock(BigInteger.class);
Date date = JMockData.mock(Date.class);
String str = JMockData.mock(String.class);

JAVA对象

模拟bean,被模拟的数据最好是plain bean,通过反射给属性赋值。

支持模拟继承而来的属性。

//模拟Java对象
public class BasicBean {
  //基本类型
  private byte byteNum;
  private boolean booleanNum;
  private char charNum;
  private short shortNum;
  private int integerNum;
  private long longNum;
  private float floatNum;
  private double doubleNum;
  //基本包装类型
  private Byte byteBoxing;
  private Boolean booleanBoxing;
  private Character charBoxing;
  private Short shortBoxing;
  private Integer integerBoxing;
  private Long longBoxing;
  private Float floatBoxing;
  private Double doubleBoxing;
  //基本类型数组
  private byte[] byteNumArray;
  private boolean[] booleanNumArray;
  private char[] charNumArray;
  private short[] shortNumArray;
  private int[] integerNumArray;
  private long[] longNumArray;
  private float[] floatNumArray;
  private double[] doubleNumArray;
  //基本类型二维数组
  private byte[][] byteNumDoubleArray;
  private boolean[][] booleanNumDoubleArray;
  private char[][] charNumDoubleArray;
  private short[][] shortNumDoubleArray;
  private int[][] integerNumDoubleArray;
  private long[][] longNumDoubleArray;
  private float[][] floatNumDoubleArray;
  private double[][] doubleNumDoubleArray;
  //基本包装类型数组
  private Byte[] byteBoxingArray;
  private Boolean[] booleanBoxingArray;
  private Character[] charBoxingArray;
  private Short[] shortBoxingArray;
  private Integer[] integerBoxingArray;
  private Long[] longBoxingArray;
  private Float[] floatBoxingArray;
  private Double[] doubleBoxingArray;
  //基本包装类型二维数组
  private Byte[][] byteBoxingDoubleArray;
  private Boolean[][] booleanBoxingDoubleArray;
  private Character[][] charBoxingDoubleArray;
  private Short[][] shortBoxingDoubleArray;
  private Integer[][] integerBoxingDoubleArray;
  private Long[][] longBoxingDoubleArray;
  private Float[][] floatBoxingDoubleArray;
  private Double[][] doubleBoxingDoubleArray;
  //其他常用类型
  private BigDecimal bigDecimal;
  private BigInteger bigInteger;
  private Date date;
  private String string;
  //其他常用类型数组
  private BigDecimal[] bigDecimalArray;
  private BigInteger[] bigIntegerArray;
  private Date[] dateArray;
  private String[] stringArray;
  //其他常用类型二维数组
  private BigDecimal[][] bigDecimalDoubleArray;
  private BigInteger[][] bigIntegerDoubleArray;
  private Date[][] dateDoubleArray;
  private String[][] stringDoubleArray;
  //集合、MAP数组
  private List<Integer>[] listArray;
  private Set<Integer>[] setArray;
  private Map<Integer, String>[] mapArray;
  //集合、MAP二维数组
  private List<Integer>[][] listDoubleArray;
  private Set<Integer>[][] setDoubleArray;
  private Map<Integer, String>[][] mapDoubleArray;
  //集合、MAP二维数组(内部数组)
  private List<Integer[]>[][] listInnerArrayDoubleArray;
  private Set<Integer[]>[][] setInnerArrayDoubleArray;
  private Map<Integer[], String[]>[][] mapInnerArrayDoubleArray;
  //集合、MAP二维数组(内部二维数组)
  private List<Integer[][]>[][] listInnerDoubleArrayDoubleArray;
  private Set<Integer[][]>[][] setInnerDoubleArrayDoubleArray;
  private Map<Integer[][], String[][]>[][] mapInnerDoubleArrayDoubleArray;
  //LIST
  private List<Byte> byteBoxingList;
  private List<Boolean> booleanBoxingList;
  private List<Character> charBoxingList;
  private List<Short> shortBoxingList;
  private List<Integer> integerBoxingList;
  private List<Long> longBoxingList;
  private List<Float> floatBoxingList;
  private List<Double> doubleBoxingList;
  private List<BigDecimal> bigDecimalList;
  private List<BigInteger> bigIntegerList;
  private List<Date> dateList;
  private List<String> stringList;
  private List<List<String>> stringListList;
  private List<Set<String>> stringSetList;
  private List<Map<Integer, String>> mapList;
  //数组LIST
  private List<Byte[]> byteBoxingArrayList;
  private List<Boolean[]> booleanBoxingArrayList;
  private List<Character[]> charBoxingArrayList;
  private List<Short[]> shortBoxingArrayList;
  private List<Integer[]> integerBoxingArrayList;
  private List<Long[]> longBoxingArrayList;
  private List<Float[]> floatBoxingArrayList;
  private List<Double[]> doubleBoxingArrayList;
  private List<BigDecimal[]> bigDecimalArrayList;
  private List<BigInteger[]> bigIntegerArrayList;
  private List<Date[]> dateArrayList;
  private List<String[]> stringArrayList;
  //二维数组LIST
  private List<Byte[][]> byteBoxingDoubleArrayList;
  private List<Boolean[][]> booleanBoxingDoubleArrayList;
  private List<Character[][]> charBoxingDoubleArrayList;
  private List<Short[][]> shortBoxingDoubleArrayList;
  private List<Integer[][]> integerBoxingDoubleArrayList;
  private List<Long[][]> longBoxingDoubleArrayList;
  private List<Float[][]> floatBoxingDoubleArrayList;
  private List<Double[][]> doubleBoxingDoubleArrayList;
  private List<BigDecimal[][]> bigDecimalDoubleArrayList;
  private List<BigInteger[][]> bigIntegerDoubleArrayList;
  private List<Date[][]> dateDoubleArrayList;
  private List<String[][]> stringDoubleArrayList;
  //SET忽略同List
  //MAP
  private Map<String, Integer> basicMap;
  private Map<String[], Integer> keyArrayMap;
  private Map<String, Integer[]> valueArrayMap;
  private Map<String[], Integer[]> keyValueArrayMap;
  private Map<String[][], Integer[][]> keyValueDoubleArrayMap;
  private Map<List<String>, Map<String, Integer>> keyListValueMapMap;
  private Map<List<String>[], Map<String, Integer>[]> keyArrayListValueArrayMapMap;
  //getter setter省略...
}

//调用模拟数据的方法模拟Java对象
BasicBean basicBean = JMockData.mock(BasicBean.class);

容器类型(LIST,SET,MAP)

@Test
//******注意TypeReference要加{}才能模拟******
public void testTypeRefrence() {
  //模拟基础类型,不建议使用这种方式,参考基础类型章节直接模拟。
  Integer integerNum = JMockData.mock(new TypeReference<Integer>(){});
  Integer[] integerArray = JMockData.mock(new TypeReference<Integer[]>(){});
  //模拟集合
  List<Integer> integerList = JMockData.mock(new TypeReference<List<Integer>>(){});
  //模拟数组集合
  List<Integer[]> integerArrayList = JMockData.mock(new TypeReference<List<Integer[]>>(){});
  //模拟集合数组
  List<Integer>[] integerListArray = JMockData.mock(new TypeReference<List<Integer>[]>(){});
  //模拟集合实体
  List<BasicBean> basicBeanList = JMockData.mock(new TypeReference<List<BasicBean>>(){});
  //各种组合忽略。。。。map同理。下面模拟一个不知道什么类型的map
  Map<List<Map<Integer, String[][]>>, Map<Set<String>, Double[]>> some = JMockData.mock(new TypeReference<Map<List<Map<Integer, String[][]>>, Map<Set<String>, Double[]>>>(){});
}

更改随机范围以及排除某些不模拟数据的字段

字段支持三种模式匹配,可快速配置:[*FieldWord*]、[*FieldWord]、[FieldWord*]

MockConfig mockConfig = new MockConfig()
            // 全局配置
            .globalConfig()
            .setEnabledStatic(false);
            .setEnabledPrivate(false);
            .setEnabledPublic(false);
            .setEnabledProtected(false);
            .sizeRange(1,1)
            .charSeed((char) 97, (char) 98)
            .byteRange((byte) 0, Byte.MAX_VALUE)
            .shortRange((short) 0, Short.MAX_VALUE)

            // 某些字段(名等于integerNum的字段、包含float的字段、double开头的字段)配置
            .subConfig("integerNum","*float*","double*")
            .intRange(10, 11)
            .floatRange(1.22f, 1.50f)
            .doubleRange(1.50,1.99)

            // 某个类的某些字段(long开头的字段、date结尾的字段、包含string的字段)配置。
            .subConfig(BasicBean.class,"long*","*date","*string*")
            .longRange(12, 13)
            .dateRange("2018-11-20", "2018-11-30")
            .stringSeed("SAVED", "REJECT", "APPROVED")
            .sizeRange(1,1)

            // 全局配置
            .globalConfig()
            // 排除所有包含list/set/map字符的字段。表达式不区分大小写。
            .excludes("*List*","*Set*","*Map*")
            // 排除所有Array开头/Boxing结尾的字段。表达式不区分大小写。
            .excludes(BasicBean.class,"*Array","Boxing*");
    BasicBean basicBean = JMockData.mock(BasicBean.class, mockConfig);

高级特性

设置小数位数

 public void testDecimalScaleMock() {
    MockConfig mockConfig = new MockConfig()
            .doubleRange(-1.1d,9999.99999d)
            .floatRange(-1.11111f,9999.99999f)
            .decimalScale(3) // 设置小数位数为3,默认是2
            .globalConfig();
    JMockData.mock(BigDecimal.class,mockConfig);
  }

根据正则模拟数据

支持\w \W \d \D \s \S

支持[0-9a-zA-Z] [abc123_]

支持{n} {n,} {n,m}

支持 * + . ?

不支持其他,如() ^ $ | \n \t \cx \b \B \f 等等

   /**
    * 根据正则模拟数据
    * 正则优先于其他规则
    */
   @Test
   public void testRegexMock() {
     MockConfig mockConfig = new MockConfig()
                 // 随机段落字符串
                 .stringRegex("I'am a nice man\\.And I'll just scribble the characters, like:[a-z]{2}-[0-9]{2}-[abc123]{2}-\\w{2}-\\d{2}@\\s{1}-\\S{1}\\.?-.")
                 // 邮箱
                 .subConfig(RegexTestDataBean.class,"userEmail")
                 .stringRegex("[a-z0-9]{5,15}\\@\\w{3,5}\\.[a-z]{2,3}")
                 // 用户名规则
                 .subConfig(RegexTestDataBean.class,"userName")
                 .stringRegex("[a-zA-Z_]{1}[a-z0-9_]{5,15}")
                 // 年龄
                 .subConfig(RegexTestDataBean.class,"userAge")
                 .numberRegex("[1-9]{1}\\d?")
                 // 用户现金
                 .subConfig(RegexTestDataBean.class,"userMoney")
                 .numberRegex("[1-9]{2}\\.\\d?")
                 // 用户的得分
                 .subConfig(RegexTestDataBean.class,"userScore")
                 .numberRegex("[1-9]{1}\\d{1}")
                 // 用户身价
                 .subConfig(RegexTestDataBean.class,"userValue")
                 .numberRegex("[1-9]{1}\\d{3,8}")
                 .globalConfig();

   }

循环依赖

public class AXB {
  private BXA BXA;
  private String name;
  //getter setter省略...
}
public class BXA {
  private AXB AXB;
  private String name;
  //getter setter省略...
}
@Test
public void testCircular() {
   AXB axb = JMockData.mock(AXB.class);
   AXB circularAxb = axb.getBXA().getAXB();
   assertSame(axb, circularAxb);
}

自依赖

public class SelfRefData {

  private Integer id;
  private String name;
  private SelfRefData parent;
  private Map<SelfRefData, SelfRefData> parentMap;
  private SelfRefData[] parentArray;
  private List<SelfRefData> list;
  private List<SelfRefData[]> listArray;
  private List<List<SelfRefData[]>> listListArray;
  private List<SelfRefData>[] arrayList;

  private SelfRefData[][][] data;
  private Map<SelfRefData, SelfRefData[]> mapArray;
  private Map<SelfRefData, List<SelfRefData>> mapList;
  private Map<SelfRefData, List<SelfRefData[]>> mapListArray;
  //getter setter省略...
}
@Test
public void testSelf() {
   SelfRefData selfRefData = JMockData.mock(SelfRefData.class);
   assertSame(selfRefData.getParent(), selfRefData);
}

泛型继承

//定义一个泛型父类
public class GenericData<A, B, C> {
  private A a;
  private B b;
  private C c;
  private A[] aArray;
  private List<B> bList;
  private Map<A, B> map;
  private List<C>[] cArray;
  private Map<Map<A, B>, List<C>>[] d;
  //getter setter省略...
}

@Test
public void testGenericData() {
    GenericData<Integer, String, BasicBean> genericData = JMockData.mock(new TypeReference<GenericData<Integer, String, BasicBean>>() {});
    assertNotNull(genericData);
  }

自定义Mocker类注册

MockConfig mockConfig = new MockConfig()
            .registerMocker(Mocker mocker, Class<T>... clazzs)

定义BeanMocker拦截器

通过实现接口BeanMockerInterceptor实现模拟bean时拦截功能,改变模拟行为

拦截器返回值类型说明:

  • 返回InterceptType.UNMOCK 不模拟, 排除此字段的模拟
  • 返回InterceptType.MOCK 自动模拟
  • 其他返回值,作为field的值通过反射注入
MockConfig mockConfig = new MockConfig()
           .registerBeanMockerInterceptor(new BeanMockerInterceptor() {...}) // 全局拦截
           .registerBeanMockerInterceptor(SimpleBean.class,new BeanMockerInterceptor<SimpleBean>() {...})// 类型拦截

jmockdata's People

Contributors

huayanyu avatar jiangcaijun avatar jsonzoup avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jmockdata's Issues

mock希望能针对静态属性进行过滤,或添加配置设置是否启用

Caused by: java.lang.IllegalAccessException: Can not set static final long field com.aaa.serialVersionUID to java.lang.Long
at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:76)
at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:80)
at sun.reflect.UnsafeQualifiedStaticLongFieldAccessorImpl.set(UnsafeQualifiedStaticLongFieldAccessorImpl.java:77)
at java.lang.reflect.Field.set(Field.java:764)
at com.github.jsonzou.jmockdata.util.ReflectionUtils.setFieldValue(ReflectionUtils.java:42)
at com.github.jsonzou.jmockdata.mocker.BeanMocker.setFieldValueByFieldAccessible(BeanMocker.java:67)
at com.github.jsonzou.jmockdata.mocker.BeanMocker.mock(BeanMocker.java:41)
... 5 more

有意参加项目

未搜索到有效的联系方式,特提ISSUE,对此项目有兴趣,有意参加项目.
现为mybatis-plus成员,QQ332309254.

能否支持LocalDate和LocalDateTime

实体bean里添加LocalDate和LocalDateTime属性,生成mock报错:java.lang.InstantiationException

具体在BeanMocker里第30行
Object result = clazz.newInstance();
LocalDate是无法newInstance的

能否给某个类单独设定模拟范围

我看模拟范围设置都是在config来设置

MockConfig mockConfig = new MockConfig()
    .byteRange((byte) 0, Byte.MAX_VALUE)
    .shortRange((short) 0, Short.MAX_VALUE)
    .intRange(0, Integer.MAX_VALUE)
    .floatRange(0.0f, Float.MAX_EXPONENT)
    .doubleRange(0.0, Double.MAX_VALUE)
    .longRange(0, Long.MAX_VALUE)
    .dateRange("2010-01-01", "2020-12-30")
    .sizeRange(5, 10)
    .stringSeed("a", "b", "c")
    .charSeed((char) 97, (char) 98);

这样的话是全局都享受这个配置。

但是我想某个class单独设定范围,比如user这个class里的int是1到5;school这个class里的int是10到20。

mockConfig.intRange(1, 5, User.class);
mockConfig.intRange(10, 20, School.class);

甚至可以精确到属性:

mockConfig.intRange(1, 5, User.class, "age");
mockConfig.intRange(10, 20, School.class, "createYear");

建议后续版本升级能够加上这个特性。

MapMocker 数组下标越界bug

com.github.jsonzou.jmockdata.mocker.MapMocker#mock
line:25 ,存在java.lang.ArrayIndexOutOfBoundsException: 异常。

bug 复现:
@test
public void testMockData (){
//当 mock Map 类型时 不指定 泛型类型 ,会出现 数组下标越界问题
Map mock = JMockData.mock(Map.class);
System.out.println(JSON.toJSONString(mock));
}

循环引用问题

如果一个类有一个类型为自身的字段,则mock这个对象的时候时会进入死循环。

public class CircularDependencyMockTest {

    public static void main(String[] args) {

        CircularDependencyObj obj = JMockData.mock(CircularDependencyObj.class);

        System.out.println(obj);

    }

    public static class CircularDependencyObj {
        
        @Getter
        @Setter
        private String field;

        @Getter
        @Setter
        private CircularDependencyObj obj;
    }
}

继承自泛型父类的Bean的Mock过程抛出null异常

继承自泛型父类的Bean的Mock过程抛出null异常
RealData createMock = JMockData.mock(RealData.class);

/**
 * 父类,省略get/set方法
 * @param <T>
 * @param <D>
 */
public static class BaseData<T,D>{
    private T time;
    private D data;
}

/**
 * 子类
 */
public static class RealData extends BaseData<Date,String>{
}

timestamp报错

Caused by: com.github.jsonzou.jmockdata.MockException: com.github.jsonzou.jmockdata.MockException: java.lang.InstantiationException: java.sql.Timestamp
at com.github.jsonzou.jmockdata.mocker.BeanMocker.mock(BeanMocker.java:63)
at com.github.jsonzou.jmockdata.mocker.ClassMocker.mock(ClassMocker.java:38)
at com.github.jsonzou.jmockdata.mocker.BaseMocker.mock(BaseMocker.java:35)
at com.github.jsonzou.jmockdata.mocker.BeanMocker.mock(BeanMocker.java:57)
... 130 common frames omitted
Caused by: com.github.jsonzou.jmockdata.MockException: java.lang.InstantiationException: java.sql.Timestamp
at com.github.jsonzou.jmockdata.mocker.BeanMocker.mock(BeanMocker.java:63)
at com.github.jsonzou.jmockdata.mocker.ClassMocker.mock(ClassMocker.java:38)
at com.github.jsonzou.jmockdata.mocker.BaseMocker.mock(BaseMocker.java:35)
at com.github.jsonzou.jmockdata.mocker.BeanMocker.mock(BeanMocker.java:57)
... 133 common frames omitted
Caused by: java.lang.InstantiationException: java.sql.Timestamp
at java.lang.Class.newInstance(Class.java:427)
at com.github.jsonzou.jmockdata.mocker.BeanMocker.mock(BeanMocker.java:35)
... 136 common frames omitted
Caused by: java.lang.NoSuchMethodException: java.sql.Timestamp.()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.newInstance(Class.java:412)
... 137 common frames omitted

构造List存在为空

JMockData.mockCollection(new TypeReference<List>() {})。可能会构造出一个空的List

嵌套泛型会导致堆栈溢出(StackOverflowError)

1、示例

OuterBean

public class OuterBean<T> {

    private T result;

    public T getResult() {
        return result;
    }

    public void setResult(T result) {
        this.result = result;
    }
}

ArrayBean

public class ArrayBean<T> {

    private List<T> list;

    public List<T> getList() {
        return list;
    }

    public void setList(List<T> list) {
        this.list = list;
    }
}

代码

OuterBean<ArrayBean<BasicBean>> outerBean = JMockData.mock(new TypeReference<OuterBean<ArrayBean<BasicBean>>>() {
        });

2、原因

  • 1.MockConfig.init只对当前类泛型做了缓存,导致嵌套泛型无法解析,通过getVariableType获取为null
  • 2.BaseMocker和ArrayMocker中对于TypeVariable处理获取为name,导致相同名称如T返回相同的Type导致StackOverflowError

3、修复建议

MockConfig.init修改如下

public MockConfig init(Type type) {
    if (!(type instanceof ParameterizedType)) {
        return this;
    }

    ParameterizedType paramType = ((ParameterizedType) type);

    Class<?> clazz = (Class<?>) paramType.getRawType();
    Type[] types = paramType.getActualTypeArguments();

    Class<?> supperClazz = clazz;
    while (supperClazz != null && !ReflectionUtils.isSystemClass(clazz.getName())) {
        TypeVariable<?>[] typeVariables = supperClazz.getTypeParameters();
        for (int index = 0; index < typeVariables.length; index++) {
            TypeVariable<?> typeVariable = typeVariables[index];

            String name = ReflectionUtils.getTypeVariableName(typeVariable);

            Type nestType = types[index];

            typeVariableCache.put(name, nestType);

            if (supperClazz == clazz) {
                init(nestType);
            }
        }

        supperClazz = supperClazz.getSuperclass();
    }

    return this;
}

BaseMocker和ArrayMocker获取name修改如下

public static String getTypeVariableName(TypeVariable<?> typeVariable) {
    GenericDeclaration declaration = typeVariable.getGenericDeclaration();
    if (!(declaration instanceof Class<?>)) {
        throw new MockException("unknown error");
    }

    return String.format("%s.%s", ((Class<?>) declaration).getName(), typeVariable.getName());
}

public static boolean isSystemClass(String name) {
    return name.startsWith("java.") || name.startsWith("javax.");
}

Junit

@Test
public void testNestedGeneric() {
    OuterBean<ArrayBean<BasicBean>> outerBean = JMockData.mock(new TypeReference<OuterBean<ArrayBean<BasicBean>>>() {
    });
    System.out.println(JSON.toJSONString(outerBean, true));
    assertNotNull(outerBean);
}

@Test
public void testArrayGeneric() {
    ArrayBean<String> outerBean = JMockData.mock(new TypeReference<ArrayBean<String>>() {
    });
    System.out.println(JSON.toJSONString(outerBean, true));
    assertNotNull(outerBean);
}

发现2个问题,一起提下

  1. 不支持Java8的 LocalDateTime
  2. 如果实体类有Lombok的Accessor ,那么也无法正确生成模拟数据。
    谢谢作者的好东西!

建议新增一个比较使用的功能

getDataConfig(***,fieldName)
获取到字段
** 相关建议:

  1. 用本地代码赋值对字段赋值
    ** 使用场景:
  2. 必须使用公司创建流水号工具生成流水号,流水号生成规则无法使用正则表达式明确
  3. 某一个字段必须使用规定值

java.time.LocalDateTime 引发APP崩溃

Caused by: java.lang.ClassNotFoundException: Didn't find class "java.time.LocalDateTime" on path: DexPathList[[zip file

最新版适配了java.time.LocalDateTime
但是低版本的jdk不支持

是否切换到上一个版本就能解决问题呢

JDK8枚举报错Field field = clazz.getDeclaredField("$VALUES");

Enum[] enums = mockConfig.getcacheEnum(clazz.getName());
if (enums == null) {
try {
Field field = clazz.getDeclaredField("$VALUES");
field.setAccessible(true);
enums = (Enum[]) field.get(clazz);
if (enums.length == 0) {
throw new MockException("空的enum不能模拟");
}
mockConfig.cacheEnum(clazz.getName(), enums);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new MockException(e);
}
}
return (T) enums[RandomUtils.nextInt(0, enums.length)];
}

java.sql.Timestamp是否支持

Caused by: com.github.jsonzou.jmockdata.MockException: java.lang.InstantiationException: java.sql.Timestamp
at com.github.jsonzou.jmockdata.mocker.BeanMocker.mock(BeanMocker.java:43)
at com.github.jsonzou.jmockdata.mocker.ClassMocker.mock(ClassMocker.java:36)
at com.github.jsonzou.jmockdata.mocker.BaseMocker.mock(BaseMocker.java:35)
at com.github.jsonzou.jmockdata.mocker.BeanMocker.mock(BeanMocker.java:37)
... 41 more

可以放开TypeReference泛型限制,给一个自定义的机会

public class TypeReference<T> {
    private Type type;

    public TypeReference() {
        Type superClass = this.getClass().getGenericSuperclass();
        //做了一点注释
        if (!(superClass instanceof Class)) {
            this.type = ((ParameterizedType)superClass).getActualTypeArguments()[0];
        }
    }

    public Type getType() {
        return this.type;
    }
    //新增
    public void setType(Type type) {
        this.type = type;
    }
}

使用场景:需要传入的Type不明确。只能运行时获取

例子如下,

public class TestSpring {
    public static void main(String[] args) {
        TestSpring testSpring = new TestSpring();
        Method[] declaredMethods = testSpring.getClass().getDeclaredMethods();
        DefaultParameterNameDiscoverer defaultParameterNameDiscoverer = new DefaultParameterNameDiscoverer();
        for (Method declaredMethod : declaredMethods) {
            if (Modifier.isStatic(declaredMethod.getModifiers())) {
                continue;
            }
            String[] parameterNames = defaultParameterNameDiscoverer.getParameterNames(declaredMethod);
            Type[] genericParameterTypes = declaredMethod.getGenericParameterTypes();
            JSONObject jsonObject = new JSONObject();
            for (int i = 0; i < genericParameterTypes.length; i++) {
                Type genericParameterType = genericParameterTypes[i];
                Object mock;
                if (genericParameterType instanceof ParameterizedType) {
                    ParameterizedType parameterizedType = (ParameterizedType) genericParameterType;
                    TypeReference typeReference = new TypeReference();
                    typeReference.setType(parameterizedType);
                    mock = Mock.mock(typeReference);
                } else {
                    Class<?> clazz = (Class<?>) genericParameterType;
                    mock = Mock.mock(clazz);
                }
                jsonObject.put(parameterNames[i], mock);
            }
            System.out.println(jsonObject.toJSONString());
        }
    }

    public void hello(String name, Date date, User user, List<User> userList, Map<String, User> userMap) {
        
    }
}

请问能否支持public变量的mock

我的有些DTO的变量是public,并且没有get set的,mock出来的数据都是null

public class TestDto {

	public String id;

	public String name;

}

mock子类时缺失继承来的属性

public class A {
    private int a;
    
    private String s;
    
    private Date d;

    //getter setter
}

public class B extent A {
       private int b;
    
       private String c;

       //getter setter
}

public class BDataWrapper extends JmockDataWrapper {
    private B b;
    
    //getter setter
    
    public static void main(String[] args) {
        BDataWrapper b = JMockData.mock(BDataWrapper.class);
        System.out.println(JSON.toJSONString(b.getB()));
       //结果: {"a":0,"b":20,"c":"X L q h q S h p "} 
    }
}

缺少了继承来的sd属性

4.1.2版本无法处理[a-z][A-Z][0-9]这种匹配规则

在UserDefinedLetterPickerScanner的scan方法中没有把"-"加入到bounds中,导致RandomLetterPicker的constructByCharacterRange方法无法识别到"-"进而跳过了处理[a-z][A-Z][0-9]这种匹配规则,希望能尽快修复一下~
image

image

可否增加链式setter的支持

配合lombok@Accessors(chain = true)使用,链式setter在开发中还是很常见的
例如

import lombok.*;
@Data
@Accessors(chain = true)
public class User {
    private String name;
    private String email;
    private String phone;

    public static void main(String[] args) {
        User user = new User()
                .setName("aaa")
                .setEmail("[email protected]")
                .setPhone("123456789");
    }
}

但是我发现这种模式在jmockdata中并不支持
看一下一下源码,做了一些改进,增加了对链式setter的支持
希望作者采纳

public static Map<Field, Method> fieldAndSetterMethod(Class clazz) throws IntrospectionException {
        Map<Field, Method> map = new LinkedHashMap<>();
        BeanInfo beanInfo = Introspector.getBeanInfo(clazz, Object.class);
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (Field field : clazz.getDeclaredFields()) {
            for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
                if (!propertyDescriptor.getName().equals(field.getName())) {
                    continue;
                }
                if (propertyDescriptor.getWriteMethod() != null) {
                    map.put(field, propertyDescriptor.getWriteMethod());
                    break;
                }
                //方法名 属性名转换首字母大写
                String setterName = "set" + StrUtil.upperFirst(propertyDescriptor.getName());
                //根据方法名和参数类型,获取Method
                Method setterMethod = ReflectUtil.getMethod(clazz, setterName, propertyDescriptor.getPropertyType());
                if (setterMethod != null&& setterMethod.getReturnType().isAssignableFrom(clazz)) {
                    map.put(field, setterMethod);
                    break;
                }
            }
        }
        return map;
    }

其中StrUtil.upperFirst()ReflectUtil.getMethod()可以自己实现,我使用的是Hutool里面的工具类

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.