implement origin-invoker method

This commit is contained in:
金戟 2021-02-18 12:10:08 +08:00
parent 14549040d9
commit c76ed2d84a
6 changed files with 58 additions and 14 deletions

View File

@ -3,6 +3,7 @@ package com.alibaba.testable.core.accessor;
import com.alibaba.testable.core.exception.MemberAccessException;
import com.alibaba.testable.core.util.TypeUtil;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@ -127,6 +128,20 @@ public class PrivateAccessor {
}
}
public static <T> T construct(Class<?> clazz, Object... args) {
try {
Constructor<?> constructor = TypeUtil.getConstructorByNameAndParameterTypes(clazz.getDeclaredConstructors(),
TypeUtil.getClassesFromObjects(args));
if (constructor != null) {
constructor.setAccessible(true);
return (T)constructor.newInstance(args);
}
} catch (Exception e) {
throw new MemberAccessException("Failed to invoke private constructor of \"" + clazz.getSimpleName() + "\"", e);
}
throw new MemberAccessException("Private static constructor of \"" + clazz.getSimpleName() + "\" not found");
}
public static <T> T invokeStatic(Class<?> clazz, String method, Object... args) {
try {
Class<?>[] cls = TypeUtil.getClassesFromObjects(args);

View File

@ -0,0 +1,15 @@
package com.alibaba.testable.core.util;
public class CollectionUtil {
public static Object[] slice(Object[] args, int pos) {
int size = args.length - pos;
if (size <= 0) {
return new Object[0];
}
Object[] slicedArgs = new Object[size];
System.arraycopy(args, pos, slicedArgs, 0, size);
return slicedArgs;
}
}

View File

@ -31,19 +31,9 @@ public class InvokeRecordUtil {
mockContext.invokeRecord.get(mockMethodName).add(args);
LogUtil.verbose(" Mock constructor \"%s\" invoked in %s::%s", mockMethodName, testClass, testCaseName);
} else {
mockContext.invokeRecord.get(mockMethodName).add(slice(args, 1));
mockContext.invokeRecord.get(mockMethodName).add(CollectionUtil.slice(args, 1));
LogUtil.verbose(" Mock method \"%s\" invoked in %s::%s\"", mockMethodName, testClass, testCaseName);
}
}
private static Object[] slice(Object[] args, int firstIndex) {
int size = args.length - firstIndex;
if (size <= 0) {
return new Object[0];
}
Object[] slicedArgs = new Object[size];
System.arraycopy(args, firstIndex, slicedArgs, 0, size);
return slicedArgs;
}
}

View File

@ -1,5 +1,6 @@
package com.alibaba.testable.core.util;
import com.alibaba.testable.core.accessor.PrivateAccessor;
import com.alibaba.testable.core.model.MockContext;
import java.util.HashSet;
@ -40,7 +41,13 @@ public class MockAssociationUtil {
}
public static Object invokeOrigin(Class<?> originClass, String originMethod, Object... args) {
return null;
if (originMethod.equals("<init>")) {
return PrivateAccessor.construct(originClass, args);
} else if (args[0] == null) {
return PrivateAccessor.invokeStatic(originClass, originMethod, CollectionUtil.slice(args, 1));
} else {
return PrivateAccessor.invoke(args[0], originMethod, CollectionUtil.slice(args, 1));
}
}
private static boolean isAssociatedByInnerMockClass(String testClassName, String mockClassName) {

View File

@ -1,5 +1,6 @@
package com.alibaba.testable.core.util;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
@ -21,6 +22,22 @@ public class TypeUtil {
return cs;
}
/**
* get constructor by parameter matching
* @param availableConstructors available constructors
* @param parameterTypes class to look for
* @return constructor which match the parameter classes
*/
public static Constructor<?> getConstructorByNameAndParameterTypes(Constructor<?>[] availableConstructors,
Class<?>[] parameterTypes) {
for (Constructor<?> c : availableConstructors) {
if (typeEquals(c.getParameterTypes(), parameterTypes)) {
return c;
}
}
return null;
}
/**
* get method by name and parameter matching
* @param availableMethods available methods

View File

@ -5,12 +5,12 @@ import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class InvokeRecordUtilTest {
class CollectionUtilTest {
@Test
void should_slice_array() {
Object[] args = new Object[]{"1", "2", "3"};
Object[] slicedArgs = PrivateAccessor.invokeStatic(InvokeRecordUtil.class, "slice", args, 1);
Object[] slicedArgs = PrivateAccessor.invokeStatic(CollectionUtil.class, "slice", args, 1);
assertEquals(2, slicedArgs.length);
assertEquals("2", slicedArgs[0]);
assertEquals("3", slicedArgs[1]);