Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jmockdata 4.4.0 #67

Open
wants to merge 4 commits into
base: jmockdata-4.3.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion src/main/java/com/github/jsonzou/jmockdata/DataConfig.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.github.jsonzou.jmockdata;

import java.math.BigDecimal;

import com.github.jsonzou.jmockdata.util.StringUtils;

/**
* @Author: jsonzou
* @Date: 2018/10/29 13:24
Expand Down Expand Up @@ -30,8 +34,24 @@ public class DataConfig {

private String numberRegex = null;
private String stringRegex = null;

// 直接设置的值!!!
private String val;

public DataConfig setVal(String val) {
this.val = val;
return this;
}

public String getVal() {
return val;
}

public BigDecimal getValNum() {
return StringUtils.isEmpty(this.val) ? null : new BigDecimal(this.val);
}

public DataConfig(MockConfig config) {
public DataConfig(MockConfig config) {
this.config = config;
}

Expand All @@ -42,6 +62,10 @@ public DataConfig(MockConfig config) {
public MockConfig globalConfig(){
return this.config;
}

public <T> Mocker<T> getMocker(Class<T> clazz) {
return globalConfig().getMocker(clazz);
}

/**
* 配置转路器 - 切换设置全局字段模拟配置
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@

/**
* Project Name: jmockdata
* File Name: GlobalBeanMockerInterceptor.java
* @date 2022年1月17日 下午7:37:48
* Copyright (c) 2022 jpq.com All Rights Reserved.
*/

package com.github.jsonzou.jmockdata;

import java.lang.reflect.Field;
import java.math.BigDecimal;

import com.github.jsonzou.jmockdata.annotation.MockValue;
import com.github.jsonzou.jmockdata.mocker.BaseMocker;
import com.github.jsonzou.jmockdata.util.ReflectionUtils;
import com.github.jsonzou.jmockdata.util.StringUtils;

/**
* TODO <br/>
* @date 2022年1月17日 下午7:37:48
* @author jpq
* @version
*/
public class GlobalBeanMockerInterceptor<T> implements BeanMockerInterceptor<T> {
@Override
public Object mock(Class<T> clazz, Field field, T bean, DataConfig dataConfig) throws IllegalAccessException {
MockValue mockValue = field.getAnnotation(MockValue.class);
if(null != mockValue) {
boolean isCharSeq = ReflectionUtils.isCharSeq(field.getType());
if(StringUtils.isNotEmpty(mockValue.value())) {
if(isCharSeq) {
field.set(bean, mockValue.value());
} else {
field.set(bean, dataConfig.setVal(mockValue.value()).getMocker(field.getType()).mock(dataConfig));
dataConfig.setVal(null);
}
return InterceptType.UNMOCK;
}
if(StringUtils.isNotEmpty(mockValue.regex())) {
dataConfig.subConfig(clazz, field.getName());
Runnable func = null;
if(isCharSeq) {
dataConfig.stringRegex(mockValue.regex());
func = () -> dataConfig.stringRegex(null);
} else {
dataConfig.numberRegex(mockValue.regex());
func = () -> dataConfig.numberRegex(null);
}
field.set(bean, new BaseMocker<>(field.getGenericType()).mock(dataConfig));
func.run();
return InterceptType.UNMOCK;
}
// if(!StringUtils.isAnyBlank(mockValue.rangeMin(), mockValue.rangeMax())) {
// dataConfig.subConfig(clazz, field.getName()).dateRange(mockValue.rangeMin(), mockValue.rangeMax());
// return InterceptType.MOCK;
// }
}
return InterceptType.MOCK;
}
}
18 changes: 18 additions & 0 deletions src/main/java/com/github/jsonzou/jmockdata/JMockData.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.github.jsonzou.jmockdata;

import java.lang.reflect.Type;

import com.github.jsonzou.jmockdata.mocker.BaseMocker;

/**
Expand Down Expand Up @@ -62,4 +64,20 @@ public static <T> T mock(TypeReference<T> typeReference, MockConfig mockConfig)
return new BaseMocker<T>(typeReference.getType()).mock(config);
}


public static <T> T mock(Type type) {
return mock(type, new MockConfig());
}

public static <T> T mock(Type type, MockConfig mockConfig) {
mockConfig.init(type);
DataConfig config=mockConfig.globalDataConfig();
return new BaseMocker<T>(type).mock(config);
}

public static <T> T mock(Type type, DataConfig dataConfig) {
MockConfig mockConfig = dataConfig.globalConfig();
mockConfig.init(type);
return new BaseMocker<T>(type).mock(dataConfig);
}
}
33 changes: 25 additions & 8 deletions src/main/java/com/github/jsonzou/jmockdata/MockConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
import com.github.jsonzou.jmockdata.annotation.MockIgnore;
import com.github.jsonzou.jmockdata.mocker.*;
import com.github.jsonzou.jmockdata.util.FieldMatchingResolver;
import com.github.jsonzou.jmockdata.util.ReflectionUtils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
Expand All @@ -37,6 +39,7 @@ public class MockConfig {
private static final LocalDateMocker LOCAL_DATE_MOCKER = new LocalDateMocker();
private static final LocalTimeMocker LOCAL_TIME_MOCKER = new LocalTimeMocker();
private static final TimestampMocker TIMESTAMP_MOCKER = new TimestampMocker();
private static final InstantMocker INSTANT_MOCKER = new InstantMocker();
private boolean enabledCircle = false;
private boolean enabledStatic = false;
private boolean enabledPublic = true;
Expand Down Expand Up @@ -96,6 +99,8 @@ public MockConfig() {
registerMocker(LOCAL_DATE_MOCKER, LocalDate.class);
registerMocker(LOCAL_TIME_MOCKER, LocalTime.class);
registerMocker(TIMESTAMP_MOCKER, Timestamp.class);
registerMocker(INSTANT_MOCKER, Instant.class);
registerBeanMockerInterceptor(new GlobalBeanMockerInterceptor<>());
}

/**
Expand Down Expand Up @@ -123,16 +128,28 @@ public Enum[] getcacheEnum(String enumClassName) {
}

public MockConfig init(Type type) {
if (type instanceof ParameterizedType) {
Class clazz = (Class) ((ParameterizedType) type).getRawType();
Type[] types = ((ParameterizedType) type).getActualTypeArguments();
TypeVariable[] typeVariables = clazz.getTypeParameters();
if (typeVariables != null && typeVariables.length > 0) {
for (int index = 0; index < typeVariables.length; index++) {
typeVariableCache.put(typeVariables[index].getName(), types[index]);
if (null == type || !(type instanceof ParameterizedType)) {
return this;
}
ParameterizedType paramType = (ParameterizedType) type; // 原始类型Rest<PageVo<DetailVO<>>>
Class<?> clazz = (Class<?>) paramType.getRawType(); // Rest
Type[] types = paramType.getActualTypeArguments(); // PageVo<DetailVO<>>

Class<?> supperClazz = clazz;
while (supperClazz != null && !ReflectionUtils.isSystemClass(clazz.getName())) {
TypeVariable<?>[] typeVariables = supperClazz.getTypeParameters(); // Rest的泛型 T
if(typeVariables == null || typeVariables.length == 0) {
break;
}
}
for (int index = 0; index < typeVariables.length; index++) { // Rest.T : PageVo<DetailVO<>>
typeVariableCache.put(ReflectionUtils.getTypeVariableName(typeVariables[index]), types[index]);
if (supperClazz == clazz) {
init(types[index]);
}
}
supperClazz = supperClazz.getSuperclass();
}

return this;
}

Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/github/jsonzou/jmockdata/Mocker.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/**
* 模拟器接口
*/
@FunctionalInterface
public interface Mocker<T> {

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

/**
* Project Name: fast-flowable-api
* File Name: MockValue.java
* @date 2022年1月17日 下午1:24:48
* Copyright (c) 2022 jpq.com All Rights Reserved.
*/

package com.github.jsonzou.jmockdata.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* @MockIgnore 优先级更高 <br/>
* @date 2022年1月17日 下午1:24:48
* @author jpq
* @version
*/
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MockValue {

// 默认值,优先级最高;对于布尔值,true/false
String value() default "";

// 正则格式,只支持字符串、数字!!!
String regex() default "";
}


Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.github.jsonzou.jmockdata.MockConfig;
import com.github.jsonzou.jmockdata.Mocker;
import com.github.jsonzou.jmockdata.util.RandomUtils;
import com.github.jsonzou.jmockdata.util.ReflectionUtils;

import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
Expand Down Expand Up @@ -95,7 +97,7 @@ private Map<Integer, Map<Class, Type[]>> map(DataConfig mockConfig, GenericArray
}
if (componentType instanceof TypeVariable) {
Map<Class, Type[]> map = new HashMap<>();
map.put((Class) mockConfig.globalConfig().getVariableType(((TypeVariable) componentType).getName()), null);
map.put((Class) mockConfig.globalConfig().getVariableType(ReflectionUtils.getTypeVariableName((TypeVariable) componentType)), null);
result.put(dimension, map);
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.github.jsonzou.jmockdata.DataConfig;
import com.github.jsonzou.jmockdata.Mocker;
import com.github.jsonzou.jmockdata.util.ReflectionUtils;

import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
Expand All @@ -28,7 +29,7 @@ public T mock(DataConfig mockConfig) {
} else if (type instanceof GenericArrayType) {
mocker = new ArrayMocker(type);
} else if (type instanceof TypeVariable) {
mocker = new BaseMocker(mockConfig.globalConfig().getVariableType(((TypeVariable) type).getName()));
mocker = new BaseMocker(mockConfig.globalConfig().getVariableType(ReflectionUtils.getTypeVariableName((TypeVariable<?>) type)));
} else {
mocker = new ClassMocker((Class) type, genericTypes);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
import com.github.jsonzou.jmockdata.util.ReflectionUtils;

import java.beans.IntrospectionException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand All @@ -33,7 +36,36 @@ public Object mock(DataConfig mockConfig) {
return cacheBean;
}
}
Object result = clazz.newInstance();
Object result = null;
try {
result = clazz.newInstance();
}catch (Exception e) {
// 某些类没有构造方法,clazz.getDeclaredConstructor(); 也会报错
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
int idx = 0;
int len = 1;
for(int i=0; i<constructors.length; i++) {
if(!Modifier.isPublic(constructors[i].getModifiers())) {
continue;
}
if(len < constructors[i].getParameterCount()) {
idx = i;
len = constructors[i].getParameterCount();
}
}
Constructor<?> declaredConstructor = clazz.getDeclaredConstructors()[idx];
Object[] params = new Object[len];
Type type = null;
for(int i=0; i<len; i++) {
type = declaredConstructor.getGenericParameterTypes()[i];
if(type instanceof TypeVariable) {
type = mockConfig.globalConfig().getVariableType(ReflectionUtils.getTypeVariableName((TypeVariable<?>) type));
}
params[i] = JMockData.mock(type, mockConfig);
}
// Object param = JMockData.mock(declaredConstructor.getGenericParameterTypes()[0], mockConfig);
result = declaredConstructor.newInstance(params);
}
mockConfig.globalConfig().cacheBean(clazz.getName(), result);
/**
* 是否配置排除整个类
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.github.jsonzou.jmockdata.MockConfig;
import com.github.jsonzou.jmockdata.Mocker;
import com.github.jsonzou.jmockdata.util.RandomUtils;
import com.github.jsonzou.jmockdata.util.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;

Expand All @@ -14,6 +16,9 @@ public class BigDecimalMocker implements Mocker<BigDecimal> {

@Override
public BigDecimal mock(DataConfig mockConfig) {
if(StringUtils.isNotEmpty(mockConfig.getVal())) {
return mockConfig.getValNum();
}
return BigDecimal.valueOf(mockConfig.globalConfig().getMocker(Double.class).mock(mockConfig));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.github.jsonzou.jmockdata.MockConfig;
import com.github.jsonzou.jmockdata.Mocker;
import com.github.jsonzou.jmockdata.util.RandomUtils;
import com.github.jsonzou.jmockdata.util.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
Expand All @@ -14,6 +15,9 @@
public class BigIntegerMocker implements Mocker<BigInteger> {
@Override
public BigInteger mock(DataConfig mockConfig) {
if(StringUtils.isNotEmpty(mockConfig.getVal())) {
return mockConfig.getValNum().toBigInteger();
}
return BigInteger.valueOf(mockConfig.globalConfig().getMocker(Long.class).mock(mockConfig));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.github.jsonzou.jmockdata.MockConfig;
import com.github.jsonzou.jmockdata.Mocker;
import com.github.jsonzou.jmockdata.util.RandomUtils;
import com.github.jsonzou.jmockdata.util.StringUtils;

/**
* Boolean对象模拟器
Expand All @@ -12,6 +13,9 @@ public class BooleanMocker implements Mocker<Boolean> {

@Override
public Boolean mock(DataConfig mockConfig) {
if(StringUtils.isNotEmpty(mockConfig.getVal())) {
return "true".equals(mockConfig.getVal().toLowerCase());
}
boolean[] booleanSeed = mockConfig.booleanSeed();
return booleanSeed[RandomUtils.nextInt(0, booleanSeed.length)];
}
Expand Down
Loading