mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-01-27 12:51:00 +08:00
support access array element by index
This commit is contained in:
parent
af3af6b272
commit
206fc5486e
@ -4,6 +4,7 @@ import com.alibaba.testable.core.util.FixSizeMap;
|
|||||||
import com.alibaba.testable.core.util.TypeUtil;
|
import com.alibaba.testable.core.util.TypeUtil;
|
||||||
import com.sun.deploy.util.StringUtils;
|
import com.sun.deploy.util.StringUtils;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -147,7 +148,7 @@ public class OmniAccessor {
|
|||||||
|
|
||||||
private static int extraIndexFromQuery(String query) {
|
private static int extraIndexFromQuery(String query) {
|
||||||
return query.endsWith(BRACKET_END)
|
return query.endsWith(BRACKET_END)
|
||||||
? Integer.parseInt(query.substring(query.lastIndexOf(BRACKET_START) + 1), query.length() - 1)
|
? Integer.parseInt(query.substring(query.lastIndexOf(BRACKET_START) + 1, query.length() - 1))
|
||||||
: -1;
|
: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,8 +166,13 @@ public class OmniAccessor {
|
|||||||
nth = extraIndexFromQuery(querySegments[i]);
|
nth = extraIndexFromQuery(querySegments[i]);
|
||||||
field = TypeUtil.getFieldByName(obj.getClass(), name);
|
field = TypeUtil.getFieldByName(obj.getClass(), name);
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
|
if (field.getType().isArray() && nth >= 0) {
|
||||||
|
Object f = field.get(obj);
|
||||||
|
obj = Array.get(f, nth);
|
||||||
|
} else {
|
||||||
obj = field.get(obj);
|
obj = field.get(obj);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +182,18 @@ public class OmniAccessor {
|
|||||||
int nth = extraIndexFromQuery(querySegment);
|
int nth = extraIndexFromQuery(querySegment);
|
||||||
Field field = TypeUtil.getFieldByName(target.getClass(), name);
|
Field field = TypeUtil.getFieldByName(target.getClass(), name);
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
|
if (field.getType().isArray()) {
|
||||||
|
Object f = field.get(target);
|
||||||
|
if (nth >= 0) {
|
||||||
|
Array.set(f, nth, value);
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < Array.getLength(f); i++) {
|
||||||
|
Array.set(f, i, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
field.set(target, value);
|
field.set(target, value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,7 @@ package com.alibaba.testable.core.tool;
|
|||||||
import com.alibaba.testable.core.model.Null;
|
import com.alibaba.testable.core.model.Null;
|
||||||
import com.alibaba.testable.core.util.TypeUtil;
|
import com.alibaba.testable.core.util.TypeUtil;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.*;
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author flin
|
* @author flin
|
||||||
@ -19,9 +16,14 @@ public class OmniConstructor {
|
|||||||
return newPrimitive(clazz);
|
return newPrimitive(clazz);
|
||||||
} else if (clazz.isArray()) {
|
} else if (clazz.isArray()) {
|
||||||
return newArray(clazz);
|
return newArray(clazz);
|
||||||
} else {
|
} else if (clazz.isEnum()) {
|
||||||
return newObject(clazz);
|
return newEnum(clazz);
|
||||||
|
} else if (clazz.isInterface()) {
|
||||||
|
return newInterface(clazz);
|
||||||
|
} else if (Modifier.isAbstract(clazz.getModifiers())) {
|
||||||
|
return newAbstractClass(clazz);
|
||||||
}
|
}
|
||||||
|
return newObject(clazz);
|
||||||
} catch (NoSuchMethodException e) {
|
} catch (NoSuchMethodException e) {
|
||||||
return null;
|
return null;
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
@ -30,17 +32,11 @@ public class OmniConstructor {
|
|||||||
return null;
|
return null;
|
||||||
} catch (InvocationTargetException e) {
|
} catch (InvocationTargetException e) {
|
||||||
return null;
|
return null;
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> void appendInstance(Object target, Class<T> clazz) {
|
|
||||||
appendInstance(target, 1, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> void appendInstance(Object target, int count, Class<T> clazz) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T> T newObject(Class<T> clazz)
|
private static <T> T newObject(Class<T> clazz)
|
||||||
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
|
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||||
Constructor<?> constructor = getBestConstructor(clazz);
|
Constructor<?> constructor = getBestConstructor(clazz);
|
||||||
@ -53,6 +49,20 @@ public class OmniConstructor {
|
|||||||
return (T)ins;
|
return (T)ins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static <T> T newAbstractClass(Class<T> clazz) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> T newInterface(Class<T> clazz) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> T newEnum(Class<T> clazz)
|
||||||
|
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||||
|
T[] constants = clazz.getEnumConstants();
|
||||||
|
return constants.length > 0 ? constants[0] : null;
|
||||||
|
}
|
||||||
|
|
||||||
private static <T> T newArray(Class<T> clazz) {
|
private static <T> T newArray(Class<T> clazz) {
|
||||||
return (T)Array.newInstance(clazz.getComponentType(), 0);
|
return (T)Array.newInstance(clazz.getComponentType(), 0);
|
||||||
}
|
}
|
||||||
|
@ -7,4 +7,13 @@ public class DemoGrandChild {
|
|||||||
public DemoGrandChild(int i) {
|
public DemoGrandChild(int i) {
|
||||||
this.i = i;
|
this.i = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int get() {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(int i) {
|
||||||
|
this.i = i;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,10 @@ public class DemoParent {
|
|||||||
|
|
||||||
public DemoChild c;
|
public DemoChild c;
|
||||||
|
|
||||||
private DemoChild[] cs;
|
public DemoChild[] cs;
|
||||||
|
|
||||||
public DemoChild.SubChild sc;
|
private DemoChild.SubChild sc;
|
||||||
|
|
||||||
public DemoChild.StaticSubChild ssc;
|
private DemoChild.StaticSubChild ssc;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -73,21 +73,49 @@ class OmniAccessorTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void should_get_by_path() {
|
void should_get_by_path() {
|
||||||
DemoParent parent = prepareDemoObject();
|
DemoParent parent = prepareParentObject();
|
||||||
Object obj = PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "getByPath", parent, "c{DemoChild}/gc{DemoGrandChild}", "c/gc");
|
Object obj = PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "getByPath", parent, "c{DemoChild}/gc{DemoGrandChild}", "c/gc");
|
||||||
assertTrue(obj instanceof DemoGrandChild);
|
assertTrue(obj instanceof DemoGrandChild);
|
||||||
assertEquals(0, PrivateAccessor.<Integer>get(obj, "i"));
|
assertEquals(0, ((DemoGrandChild)obj).get());
|
||||||
|
PrivateAccessor.set(parent.c, "gcs", new DemoGrandChild[] { new DemoGrandChild(4), new DemoGrandChild(6) });
|
||||||
|
obj = PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "getByPath", parent, "c{DemoChild}/gcs{DemoGrandChild[]}", "c/gcs");
|
||||||
|
assertTrue(obj instanceof DemoGrandChild[]);
|
||||||
|
assertEquals(2, ((DemoGrandChild[])obj).length);
|
||||||
|
obj = PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "getByPath", parent, "c{DemoChild}/gcs{DemoGrandChild[]}", "c/gcs[1]");
|
||||||
|
assertTrue(obj instanceof DemoGrandChild);
|
||||||
|
assertEquals(6, ((DemoGrandChild)obj).get());
|
||||||
|
parent.cs = new DemoChild[] { null, prepareChildObject() };
|
||||||
|
obj = PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "getByPath", parent, "cs{DemoChild[]}/gcs{DemoGrandChild[]}/i{int}", "c[1]/gcs[1]/i");
|
||||||
|
assertEquals(3, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void should_set_by_path_segment() {
|
void should_set_by_path_segment() {
|
||||||
DemoParent parent = prepareDemoObject();
|
DemoParent parent = prepareParentObject();
|
||||||
|
DemoChild child = prepareChildObject();
|
||||||
PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "setByPathSegment", parent.c, "gc{DemoGrandChild}", "gc", new DemoGrandChild(2));
|
PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "setByPathSegment", parent.c, "gc{DemoGrandChild}", "gc", new DemoGrandChild(2));
|
||||||
assertEquals(2, PrivateAccessor.<Integer>get(parent.c.gc, "i"));
|
assertEquals(2, parent.c.gc.get());
|
||||||
|
PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "setByPathSegment", parent, "cs{DemoChild[]}", "cs[2]", child);
|
||||||
|
assertNull(parent.cs[0]);
|
||||||
|
assertNull(parent.cs[1]);
|
||||||
|
assertEquals(5, parent.cs[2].gc.get());
|
||||||
|
PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "setByPathSegment", parent, "cs{DemoChild[]}", "cs", child);
|
||||||
|
assertEquals(5, parent.cs[0].gc.get());
|
||||||
|
assertEquals(5, parent.cs[1].gc.get());
|
||||||
|
assertEquals(5, parent.cs[2].gc.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
private DemoParent prepareDemoObject() {
|
private DemoParent prepareParentObject() {
|
||||||
return OmniConstructor.newInstance(DemoParent.class);
|
DemoParent parent = OmniConstructor.newInstance(DemoParent.class);
|
||||||
|
parent.cs = new DemoChild[3];
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DemoChild prepareChildObject() {
|
||||||
|
DemoChild child = OmniConstructor.newInstance(DemoChild.class);
|
||||||
|
PrivateAccessor.set(child, "gcs", new DemoGrandChild[] { null, new DemoGrandChild(3) });
|
||||||
|
child.gc.set(5);
|
||||||
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user