blob: 64b7ae300283f19f342486a335d324bd81f642d0 [file] [log] [blame]
Pavlin Radoslavovd26f57a2014-10-23 17:19:45 -07001package org.onlab.junit;
Jonathan Hart20d8e512014-10-16 11:05:52 -07002
3import java.lang.reflect.Constructor;
4import java.lang.reflect.Field;
5import java.lang.reflect.InvocationTargetException;
6import java.lang.reflect.Method;
7
8
9/**
10 * Utilities for testing.
11 */
12public final class TestUtils {
13
14 /**
15 * Sets the field, bypassing scope restriction.
16 *
17 * @param subject Object where the field belongs
18 * @param fieldName name of the field to set
19 * @param value value to set to the field.
20 * @param <T> subject type
21 * @param <U> value type
22 * @throws TestUtilsException if there are reflection errors while setting
23 * the field
24 */
25 public static <T, U> void setField(T subject, String fieldName, U value)
26 throws TestUtilsException {
27 @SuppressWarnings("unchecked")
28 Class<T> clazz = (Class<T>) subject.getClass();
29 try {
30 Field field = clazz.getDeclaredField(fieldName);
31 field.setAccessible(true);
32 field.set(subject, value);
33 } catch (NoSuchFieldException | SecurityException |
34 IllegalArgumentException | IllegalAccessException e) {
35 throw new TestUtilsException("setField failed", e);
36 }
37 }
38
39 /**
40 * Gets the field, bypassing scope restriction.
41 *
42 * @param subject Object where the field belongs
43 * @param fieldName name of the field to get
44 * @return value of the field.
45 * @param <T> subject type
46 * @param <U> field value type
47 * @throws TestUtilsException if there are reflection errors while getting
48 * the field
49 */
50 public static <T, U> U getField(T subject, String fieldName)
51 throws TestUtilsException {
52 try {
53 @SuppressWarnings("unchecked")
54 Class<T> clazz = (Class<T>) subject.getClass();
55 Field field = clazz.getDeclaredField(fieldName);
56 field.setAccessible(true);
57
58 @SuppressWarnings("unchecked")
59 U result = (U) field.get(subject);
60 return result;
61 } catch (NoSuchFieldException | SecurityException |
62 IllegalArgumentException | IllegalAccessException e) {
63 throw new TestUtilsException("getField failed", e);
64 }
65 }
66
67 /**
68 * Calls the method, bypassing scope restriction.
69 *
70 * @param subject Object where the method belongs
71 * @param methodName name of the method to call
72 * @param paramTypes formal parameter type array
73 * @param args arguments
74 * @return return value or null if void
75 * @param <T> subject type
76 * @param <U> return value type
77 * @throws TestUtilsException if there are reflection errors while calling
78 * the method
79 */
80 public static <T, U> U callMethod(T subject, String methodName,
81 Class<?>[] paramTypes, Object...args) throws TestUtilsException {
82
83 try {
84 @SuppressWarnings("unchecked")
85 Class<T> clazz = (Class<T>) subject.getClass();
86 final Method method;
87 if (paramTypes == null || paramTypes.length == 0) {
88 method = clazz.getDeclaredMethod(methodName);
89 } else {
90 method = clazz.getDeclaredMethod(methodName, paramTypes);
91 }
92 method.setAccessible(true);
93
94 @SuppressWarnings("unchecked")
95 U result = (U) method.invoke(subject, args);
96 return result;
97 } catch (NoSuchMethodException | SecurityException |
98 IllegalAccessException | IllegalArgumentException |
99 InvocationTargetException e) {
100 throw new TestUtilsException("callMethod failed", e);
101 }
102 }
103
104 /**
105 * Calls the method, bypassing scope restriction.
106 *
107 * @param subject Object where the method belongs
108 * @param methodName name of the method to call
109 * @param paramType formal parameter type
110 * @param arg argument
111 * @return return value or null if void
112 * @param <T> subject type
113 * @param <U> return value type
114 * @throws TestUtilsException if there are reflection errors while calling
115 * the method
116 */
117 public static <T, U> U callMethod(T subject, String methodName,
118 Class<?> paramType, Object arg) throws TestUtilsException {
119 return callMethod(subject, methodName, new Class<?>[]{paramType}, arg);
120 }
121
122 /**
123 * Triggers an allocation of an object of type <T> and forces a call to
124 * the private constructor.
125 *
126 * @param constructor Constructor to call
127 * @param <T> type of the object to create
128 * @return created object of type <T>
129 * @throws TestUtilsException if there are reflection errors while calling
130 * the constructor
131 */
132 public static <T> T callConstructor(Constructor<T> constructor)
133 throws TestUtilsException {
134 try {
135 constructor.setAccessible(true);
136 return constructor.newInstance();
137 } catch (InstantiationException | IllegalAccessException |
138 InvocationTargetException error) {
139 throw new TestUtilsException("callConstructor failed", error);
140 }
141 }
142
143 /**
144 * Avoid instantiation.
145 */
146 private TestUtils() {}
147
148 /**
149 * Exception that can be thrown if problems are encountered while executing
150 * the utility method. These are usually problems accessing fields/methods
151 * through reflection. The original exception can be found by examining the
152 * cause.
153 */
154 public static class TestUtilsException extends Exception {
155
156 private static final long serialVersionUID = 1L;
157
158 /**
159 * Constructs a new exception with the specified detail message and
160 * cause.
161 *
162 * @param message the detail message
163 * @param cause the original cause of this exception
164 */
165 public TestUtilsException(String message, Throwable cause) {
166 super(message, cause);
167 }
168 }
169}