GithubHelp home page GithubHelp logo

jsonzou / jmockdata Goto Github PK

View Code? Open in Web Editor NEW
527.0 38.0 128.0 412 KB

The plugin to mock the java data by random.

License: Apache License 2.0

Java 100.00%
mocker java-data jmockdata jmock jmockit mock-java-data

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

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不支持

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

嵌套泛型会导致堆栈溢出(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);
}

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

我看模拟范围设置都是在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");

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

构造List存在为空

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

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));
}

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

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

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

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属性

继承自泛型父类的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>{
}

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)];
}

可否增加链式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里面的工具类

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

请问能否支持public变量的mock

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

public class TestDto {

	public String id;

	public String name;

}

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

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

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

image

循环引用问题

如果一个类有一个类型为自身的字段,则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;
    }
}

可以放开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) {
        
    }
}

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.

发现2个问题,一起提下

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

能否支持LocalDate和LocalDateTime

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

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

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.