TestUtils
- Some util methods to access private fields/methods
Change-Id: I9984d33b518ae6e0683e664895205b44d27ce47a
diff --git a/src/test/java/net/onrc/onos/core/util/TestUtils.java b/src/test/java/net/onrc/onos/core/util/TestUtils.java
new file mode 100644
index 0000000..a3606ed
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/util/TestUtils.java
@@ -0,0 +1,122 @@
+package net.onrc.onos.core.util;
+
+import static org.junit.Assert.*;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+
+/**
+ * Utils for testing.
+ */
+public final class TestUtils {
+
+ /**
+ * Sets the field, bypassing scope restriction.
+ *
+ * @param subject Object where the field belongs
+ * @param fieldName name of the field to set
+ * @param value value to set to the field.
+ * @param <T> subject type
+ * @param <U> value type
+ */
+ public static <T, U> void setField(T subject, String fieldName, U value) {
+ @SuppressWarnings("unchecked")
+ Class<T> clazz = (Class<T>) subject.getClass();
+ try {
+ Field field = clazz.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ field.set(subject, value);
+ } catch (NoSuchFieldException | SecurityException |
+ IllegalArgumentException | IllegalAccessException e) {
+ StringWriter sw = new StringWriter();
+ e.printStackTrace(new PrintWriter(sw));
+ fail(sw.toString());
+ }
+ }
+
+ /**
+ * Gets the field, bypassing scope restriction.
+ *
+ * @param subject Object where the field belongs
+ * @param fieldName name of the field to get
+ * @return value of the field.
+ * @param <T> subject type
+ * @param <U> field value type
+ */
+ public static <T, U> U getField(T subject, String fieldName) {
+ try {
+ @SuppressWarnings("unchecked")
+ Class<T> clazz = (Class<T>) subject.getClass();
+ Field field = clazz.getDeclaredField(fieldName);
+ field.setAccessible(true);
+
+ @SuppressWarnings("unchecked")
+ U result = (U) field.get(subject);
+ return result;
+ } catch (NoSuchFieldException | SecurityException |
+ IllegalArgumentException | IllegalAccessException e) {
+
+ StringWriter sw = new StringWriter();
+ e.printStackTrace(new PrintWriter(sw));
+ fail(sw.toString());
+ return null;
+ }
+ }
+
+ /**
+ * Calls the method, bypassing scope restriction.
+ *
+ * @param subject Object where the method belongs
+ * @param methodName name of the method to call
+ * @param paramTypes formal parameter type array
+ * @param args arguments
+ * @return return value or null if void
+ * @param <T> subject type
+ * @param <U> return value type
+ */
+ public static <T, U> U callMethod(T subject, String methodName, Class<?>[] paramTypes, Object...args) {
+
+ try {
+ @SuppressWarnings("unchecked")
+ Class<T> clazz = (Class<T>) subject.getClass();
+ Method method = clazz.getDeclaredMethod(methodName, paramTypes);
+ method.setAccessible(true);
+
+ @SuppressWarnings("unchecked")
+ U result = (U) method.invoke(subject, args);
+ return result;
+ } catch (NoSuchMethodException | SecurityException |
+ IllegalAccessException | IllegalArgumentException |
+ InvocationTargetException e) {
+
+ StringWriter sw = new StringWriter();
+ e.printStackTrace(new PrintWriter(sw));
+ fail(sw.toString());
+ return null;
+ }
+ }
+
+ /**
+ * Calls the method, bypassing scope restriction.
+ *
+ * @param subject Object where the method belongs
+ * @param methodName name of the method to call
+ * @param paramType formal parameter type
+ * @param arg argument
+ * @return return value or null if void
+ * @param <T> subject type
+ * @param <U> return value type
+ */
+ public static <T, U> U callMethod(T subject, String methodName, Class<?> paramType, Object arg) {
+ return callMethod(subject, methodName, new Class<?>[]{paramType}, arg);
+ }
+
+ /**
+ * Avoid instantiation.
+ */
+ private TestUtils() {}
+}
diff --git a/src/test/java/net/onrc/onos/core/util/TestUtilsTest.java b/src/test/java/net/onrc/onos/core/util/TestUtilsTest.java
new file mode 100644
index 0000000..06ccedb
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/util/TestUtilsTest.java
@@ -0,0 +1,156 @@
+package net.onrc.onos.core.util;
+
+import static org.junit.Assert.*;
+import static net.onrc.onos.core.util.TestUtils.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test and usage examples for TestUtils.
+ */
+public class TestUtilsTest {
+
+ /**
+ * Test data.
+ */
+ private static final class TestClass {
+
+ @SuppressWarnings("unused")
+ private int privateField = 42;
+
+ @SuppressWarnings("unused")
+ protected int protectedField = 2501; // CHECKSTYLE IGNORE THIS LINE
+
+ /**
+ * Protected method with multiple argument.
+ *
+ * @param x simply returns
+ * @param y not used
+ * @return x
+ */
+ @SuppressWarnings("unused")
+ private int privateMethod(Number x, Long y) {
+ return x.intValue();
+ }
+
+ /**
+ * Protected method with no argument.
+ *
+ * @return int
+ */
+ @SuppressWarnings("unused")
+ protected int protectedMethod() {
+ return 42;
+ }
+
+ /**
+ * Method returning array.
+ *
+ * @param ary random array
+ * @return ary
+ */
+ @SuppressWarnings("unused")
+ private int[] arrayReturnMethod(int[] ary) {
+ return ary;
+ }
+
+ /**
+ * Method without return value.
+ *
+ * @param s ignored
+ */
+ @SuppressWarnings("unused")
+ private void voidMethod(String s) {
+ System.out.println(s);
+ }
+ }
+
+ private TestClass test;
+
+ /**
+ * setUp.
+ */
+ @Before
+ public void setUp() {
+ test = new TestClass();
+ }
+
+ /**
+ * Example to access private field.
+ */
+ @Test
+ public void testSetGetPrivateField() {
+
+ assertEquals(42, getField(test, "privateField"));
+ setField(test, "privateField", 0xDEAD);
+ assertEquals(0xDEAD, getField(test, "privateField"));
+ }
+
+ /**
+ * Example to access protected field.
+ */
+ @Test
+ public void testSetGetProtectedField() {
+
+ assertEquals(2501, getField(test, "protectedField"));
+ setField(test, "protectedField", 0xBEEF);
+ assertEquals(0xBEEF, getField(test, "protectedField"));
+ }
+
+ /**
+ * Example to call private method and multiple parameters.
+ * <p/>
+ * It also illustrates that paramTypes must match declared type,
+ * not the runtime types of arguments.
+ */
+ @Test
+ public void testCallPrivateMethod() {
+
+ int result = callMethod(test, "privateMethod",
+ new Class<?>[] {Number.class, Long.class},
+ Long.valueOf(42), Long.valueOf(32));
+ assertEquals(42, result);
+ }
+
+ /**
+ * Example to call protected method and no parameters.
+ */
+ @Test
+ public void testCallProtectedMethod() {
+
+ int result = callMethod(test, "protectedMethod",
+ new Class<?>[] {});
+ assertEquals(42, result);
+ }
+
+ /**
+ * Example to call method returning array.
+ * <p/>
+ * Note: It is not required to receive as Object.
+ * Following is just verifying it is not Boxed arrays.
+ */
+ @Test
+ public void testCallArrayReturnMethod() {
+
+ int[] array = {1, 2, 3};
+ Object aryResult = callMethod(test, "arrayReturnMethod",
+ new Class<?>[] {int[].class}, array);
+ assertEquals(int[].class, aryResult.getClass());
+ assertArrayEquals(array, (int[]) aryResult);
+ }
+
+
+ /**
+ * Example to call void returning method.
+ * <p/>
+ * Note: Return value will be null for void methods.
+ */
+ @Test
+ public void testCallVoidReturnMethod() {
+
+ Object voidResult = callMethod(test, "voidMethod",
+ String.class, "foobar");
+ assertNull(voidResult);
+ }
+}