diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/constant/ConstPool.java b/testable-agent/src/main/java/com/alibaba/testable/agent/constant/ConstPool.java index e23feb5..27116b9 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/constant/ConstPool.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/constant/ConstPool.java @@ -16,7 +16,6 @@ public class ConstPool { public static final String MOCK_WITH = "com.alibaba.testable.core.annotation.MockWith"; public static final String MOCK_METHOD = "com.alibaba.testable.core.annotation.MockMethod"; public static final String MOCK_CONSTRUCTOR = "com.alibaba.testable.core.annotation.MockConstructor"; - public static final String TESTABLE_MOCK = "com.alibaba.testable.core.annotation.TestableMock"; public static final String CGLIB_CLASS_INFIX = "$$EnhancerBy"; diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/TestClassHandler.java b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/TestClassHandler.java index 909a608..868e7dc 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/TestClassHandler.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/TestClassHandler.java @@ -119,7 +119,6 @@ public class TestClassHandler extends BaseClassHandler { } for (AnnotationNode an : mn.visibleAnnotations) { if (ClassUtil.toByteCodeClassName(ConstPool.MOCK_METHOD).equals(an.desc) || - ClassUtil.toByteCodeClassName(ConstPool.TESTABLE_MOCK).equals(an.desc) || ClassUtil.toByteCodeClassName(ConstPool.MOCK_CONSTRUCTOR).equals(an.desc)) { return true; } diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/transformer/TestableClassTransformer.java b/testable-agent/src/main/java/com/alibaba/testable/agent/transformer/TestableClassTransformer.java index 8042d65..3786112 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/transformer/TestableClassTransformer.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/transformer/TestableClassTransformer.java @@ -155,8 +155,7 @@ public class TestableClassTransformer implements ClassFileTransformer { LogUtil.verbose(" Mock constructor \"%s\" as \"(%s)V\" for \"%s\"", mn.name, ClassUtil.extractParameters(mn.desc), ClassUtil.getReturnType(mn.desc)); addMockConstructor(methodInfos, cn, mn); - } else if (fullClassName.equals(ConstPool.MOCK_METHOD) || - fullClassName.equals(ConstPool.TESTABLE_MOCK)) { + } else if (fullClassName.equals(ConstPool.MOCK_METHOD)) { LogUtil.verbose(" Mock method \"%s\" as \"%s\"", mn.name, mn.desc); String targetMethod = AnnotationUtil.getAnnotationParameter( an, ConstPool.FIELD_TARGET_METHOD, mn.name, String.class); @@ -216,7 +215,6 @@ public class TestableClassTransformer implements ClassFileTransformer { for (AnnotationNode an : mn.visibleAnnotations) { String fullClassName = toDotSeparateFullClassName(an.desc); if (fullClassName.equals(ConstPool.MOCK_METHOD) || - fullClassName.equals(ConstPool.TESTABLE_MOCK) || fullClassName.equals(ConstPool.MOCK_CONSTRUCTOR)) { return true; } diff --git a/testable-core/src/main/java/com/alibaba/testable/core/accessor/PrivateAccessor.java b/testable-core/src/main/java/com/alibaba/testable/core/accessor/PrivateAccessor.java index d95e60e..af36b23 100644 --- a/testable-core/src/main/java/com/alibaba/testable/core/accessor/PrivateAccessor.java +++ b/testable-core/src/main/java/com/alibaba/testable/core/accessor/PrivateAccessor.java @@ -1,5 +1,6 @@ package com.alibaba.testable.core.accessor; +import com.alibaba.testable.core.exception.MemberAccessException; import com.alibaba.testable.core.util.TypeUtil; import java.lang.reflect.Field; @@ -12,14 +13,72 @@ public class PrivateAccessor { private static final String KOTLIN_COMPANION_FIELD = "Companion"; + public static class NoVerify { + public static T get(Object ref, String field) { + try { + return PrivateAccessor.get(ref, field); + } catch (MemberAccessException e) { + printError(e); + return null; + } + } + + public static void set(Object ref, String field, T value) { + try { + PrivateAccessor.set(ref, field, value); + } catch (MemberAccessException e) { + printError(e); + } + } + + public static T invoke(Object ref, String method, Object... args) { + try { + return PrivateAccessor.invoke(ref, method, args); + } catch (MemberAccessException e) { + printError(e); + return null; + } + } + + public static T getStatic(Class clazz, String field) { + try { + return PrivateAccessor.getStatic(clazz, field); + } catch (MemberAccessException e) { + printError(e); + return null; + } + } + + public static void setStatic(Class clazz, String field, T value) { + try { + PrivateAccessor.setStatic(clazz, field, value); + } catch (MemberAccessException e) { + printError(e); + } + } + + public static T invokeStatic(Class clazz, String method, Object... args) { + try { + return PrivateAccessor.invokeStatic(clazz, method, args); + } catch (MemberAccessException e) { + printError(e); + return null; + } + } + + private static void printError(MemberAccessException e) { + Throwable cause = e.getCause() == null ? e : e.getCause(); + System.err.println(cause.toString()); + } + } + public static T get(Object ref, String field) { try { Field declaredField = ref.getClass().getDeclaredField(field); declaredField.setAccessible(true); return (T)declaredField.get(ref); } catch (Exception e) { - System.err.println("Failed to get private field \"" + field + "\": " + e.toString()); - return null; + throw new MemberAccessException("Failed to get private field \"" + field + "\"", e); } } @@ -29,23 +88,23 @@ public class PrivateAccessor { declaredField.setAccessible(true); declaredField.set(ref, value); } catch (Exception e) { - System.err.println("Failed to set private field \"" + field + "\": " + e.toString()); + throw new MemberAccessException("Failed to set private field \"" + field + "\"", e); } } public static T invoke(Object ref, String method, Object... args) { try { Class[] cls = TypeUtil.getClassesFromObjects(args); - Method declaredMethod = TypeUtil.getMethodByNameAndParameterTypes(ref.getClass().getDeclaredMethods(), method, cls); + Method declaredMethod = TypeUtil.getMethodByNameAndParameterTypes(ref.getClass().getDeclaredMethods(), + method, cls); if (declaredMethod != null) { declaredMethod.setAccessible(true); return (T)declaredMethod.invoke(ref, args); } } catch (Exception e) { - System.err.println("Failed to invoke private method \"" + method + "\": " + e.toString()); - return null; + throw new MemberAccessException("Failed to invoke private method \"" + method + "\"", e); } - return null; + throw new MemberAccessException("Private method \"" + method + "\" not found"); } public static T getStatic(Class clazz, String field) { @@ -54,8 +113,7 @@ public class PrivateAccessor { declaredField.setAccessible(true); return (T)declaredField.get(null); } catch (Exception e) { - System.err.println("Failed to get private static field \"" + field + "\": " + e.toString()); - return null; + throw new MemberAccessException("Failed to get private static field \"" + field + "\"", e); } } @@ -65,7 +123,7 @@ public class PrivateAccessor { declaredField.setAccessible(true); declaredField.set(null, value); } catch (Exception e) { - System.err.println("Failed to set private static field \"" + field + "\": " + e.toString()); + throw new MemberAccessException("Failed to set private static field \"" + field + "\"", e); } } @@ -87,9 +145,8 @@ public class PrivateAccessor { return (T)declaredMethod.invoke(companionInstance, args); } } catch (Exception e) { - System.err.println("Failed to invoke private static method \"" + method + "\": " + e.toString()); - return null; + throw new MemberAccessException("Failed to invoke private static method \"" + method + "\"", e); } - return null; + throw new MemberAccessException("Private static method \"" + method + "\" not found"); } } diff --git a/testable-core/src/main/java/com/alibaba/testable/core/annotation/TestableMock.java b/testable-core/src/main/java/com/alibaba/testable/core/annotation/TestableMock.java deleted file mode 100644 index 6d4ff70..0000000 --- a/testable-core/src/main/java/com/alibaba/testable/core/annotation/TestableMock.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.alibaba.testable.core.annotation; - -import java.lang.annotation.*; - -/** - * Mark method as mock method - * @deprecated will be remove in v0.5.0, use @MockMethod or @MockConstructor instead - * - * @author flin - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -@Documented -@Deprecated -public @interface TestableMock { - - /** - * mock specified method instead of method with same name - * @return target method name - */ - String targetMethod() default ""; - -} diff --git a/testable-core/src/main/java/com/alibaba/testable/core/exception/MemberAccessException.java b/testable-core/src/main/java/com/alibaba/testable/core/exception/MemberAccessException.java new file mode 100644 index 0000000..4ad56ce --- /dev/null +++ b/testable-core/src/main/java/com/alibaba/testable/core/exception/MemberAccessException.java @@ -0,0 +1,26 @@ +package com.alibaba.testable.core.exception; + +import java.lang.reflect.InvocationTargetException; + +/** + * @author flin + */ +public class MemberAccessException extends RuntimeException { + + public MemberAccessException(String message) { + super(message); + } + + public MemberAccessException(String message, Throwable cause) { + super(message, getRootCause(cause)); + } + + private static Throwable getRootCause(Throwable cause) { + if (cause instanceof InvocationTargetException) { + return ((InvocationTargetException)cause).getTargetException(); + } else { + return cause; + } + } + +}