View Javadoc

1   /**
2    * 
3    */
4   package pl.koziolekweb.pmt;
5   
6   import java.lang.reflect.Field;
7   import java.lang.reflect.Method;
8   import java.util.Map;
9   
10  /**
11   * 
12   * <p>
13   * Klasa służy do uruchamiania metod prywatnych i ustawiania pól prywatnych
14   * obiektów w trakcie testów jednostkowych.
15   * </p>
16   * <p>
17   * <b>EN:</b> Class can run private methods, set private fields for object in unt
18   * tests.
19   * </p>
20   * 
21   * @author bartlomiejk
22   * 
23   */
24  public class PrivateMemberTester {
25  
26  	/**
27  	 * <p>
28  	 * Uruchamia wskazaną metodę. Metoda może być prywatna.
29  	 * </p>
30  	 * <p>
31  	 * <b>EN:</b> Run method. Method can be private.
32  	 * </p>
33  	 * 
34  	 * @param methodName
35  	 *            nazwa metody uruchamianej. <br/>
36  	 *            <b>EN:</b> Method name.
37  	 * @param owner
38  	 *            obiekt na rzecz, ktorego uruchamiana jest metoda. <br/>
39  	 *            <b>EN:</b> Object for which method is invoked.
40  	 * @param args
41  	 *            argumenty metody. <br/>
42  	 *            <b>EN:</b> Arguments of method.
43  	 * @param clazz
44  	 *            klasa do której należy metoda. <br/>
45  	 *            <b>EN:</b> Owner class.
46  	 * @param parameterTypes
47  	 *            tablica klas argumentów metody. <br/>
48  	 *            <b>EN:</b> Array of arguments class.
49  	 * @return to samo co wywoływana metoda. <br/>
50  	 *         <b>EN:</b> the same as invoked method.
51  	 * @throws Throwable
52  	 *             Błąd jaki został zwrocony przez wywolywaną metodę lub błąd
53  	 *             wywołania metody. <br/>
54  	 *             <b>EN:</b> Exeption from method or invoker exeption.
55  	 */
56  	public static Object runMethod(final String methodName, final Object owner,
57  			final Object[] args, final Class<?> clazz,
58  			final Class<?>... parameterTypes) throws Throwable {
59  		Object o = null;
60  		try {
61  			Method method = clazz.getDeclaredMethod(methodName, parameterTypes);
62  			method.setAccessible(true);
63  			o = method.invoke(owner, args);
64  			return o;
65  		} catch (Throwable e) {
66  			Throwable t = null;
67  			if (e.getCause() != null) {
68  				t = (Throwable) e.getCause();
69  			} else {
70  				t = e;
71  			}
72  			throw t;
73  		}
74  	}
75  
76  	/**
77  	 * <p>
78  	 * Pobiera wartość danego pola. Pole może być prywatne.
79  	 * </p>
80  	 * <p>
81  	 * <b>EN:</b> Return value of field. Field can be private.
82  	 * </p>
83  	 * 
84  	 * 
85  	 * @param fieldName
86  	 *            nazwa pola. <br/>
87  	 *            <b>EN:</b> Field name.
88  	 * @param owner
89  	 *            obiekt z ktorego czerpane są informacje o polu. <br/>
90  	 *            <b>EN:</b> Object that field will get.
91  	 * @param ownerClass
92  	 *            Klasa do której należy pole. <br/>
93  	 *            <b>EN:</b> Field class.
94  	 * @return wartość pola jako {@link Object}. <br/>
95  	 *         <b>EN:</b> field value ad {@link Object}.
96  	 * @throws NoSuchFieldException
97  	 *             jeżeli podane pole nie istnieje. <br/>
98  	 *             <b>EN:</b> If field does not exist.
99  	 */
100 	public static Object getPrivateFiled(final String fieldName,
101 			final Object owner, final Class<?> ownerClass)
102 			throws NoSuchFieldException {
103 
104 		Field declaredField = ownerClass.getDeclaredField(fieldName);
105 		declaredField.setAccessible(true);
106 		try {
107 			return declaredField.get(owner);
108 		} catch (IllegalAccessException e) {
109 			throw new RuntimeException(e);
110 		}
111 	}
112 
113 	/**
114 	 * <p>
115 	 * Metoda pozwala na ustawienie prywatnego pola.
116 	 * </p>
117 	 * <p>
118 	 * <b>EN:</b> Method allow set value to indicated field.
119 	 * </p>
120 	 * 
121 	 * @param fieldName
122 	 *            nazwa pola.<br/>
123 	 *            <b>EN:</b> Field name.
124 	 * @param owner
125 	 *            obiekt dla którego chcemy ustawić pole. <br/>
126 	 *            <b>EN:</b> Object for which field we set.
127 	 * @param value
128 	 *            nowa wartość pola. <br/>
129 	 *            <b>EN:</b> New value of field.
130 	 * @param ownerClass
131 	 *            klasa do której należy pole. <br/>
132 	 *            <b>EN:</b> Field class.
133 	 * @throws NoSuchFieldException
134 	 *             jeżeli podane pole nie istnieje. <br/>
135 	 *             <b>EN:</b> If field does not exist.
136 	 */
137 	public static void setPrivateField(final String fieldName,
138 			final Object owner, final Object value, final Class<?> ownerClass)
139 			throws NoSuchFieldException {
140 		Field declaredField = ownerClass.getDeclaredField(fieldName);
141 		declaredField.setAccessible(true);
142 		try {
143 			declaredField.set(owner, value);
144 		} catch (IllegalAccessException e) {
145 			throw new RuntimeException(e);
146 		}
147 	}
148 
149 	/**
150 	 * <p>
151 	 * Metoda ustawia wartość wskazanego pola dla wskazanego obiektu na
152 	 * <code>null</code>.
153 	 * </p>
154 	 * <p>
155 	 * <b>EN:</b> Method set <code>null</code> value for indicated field.
156 	 * </p>
157 	 * 
158 	 * @param fieldName
159 	 *            nazwa pola. <br/>
160 	 *            <b>EN:</b> Field name.
161 	 * @param owner
162 	 *            obiekt, którego pole ustawiamy. <br/>
163 	 *            <b>EN:</b> Object which field we set.
164 	 * @throws NoSuchFieldException
165 	 *             jeżeli nazwa pola jest nieprawidłowa. <br/>
166 	 *             <b>EN:</b> If field does not exist.
167 	 */
168 	public static void nullField(final String fieldName, final Object owner)
169 			throws NoSuchFieldException {
170 		Field declaredField = owner.getClass().getDeclaredField(fieldName);
171 		declaredField.setAccessible(true);
172 		try {
173 			declaredField.set(owner, null);
174 		} catch (IllegalAccessException e) {
175 			throw new RuntimeException(e);
176 		}
177 	}
178 
179 	/**
180 	 * <p>
181 	 * Metoda ustawia wszystkie podane pola z parametru <code>fields</code> na
182 	 * zadane w tej mapie wartości. Ustawianie pól mapy odbywa się na podstawie
183 	 * listy zadeklarowanych pól. Oznacza to, że podanie nieprawidłowej nazwy
184 	 * pola nie spowoduje błędu.
185 	 * </p>
186 	 * <p>
187 	 * <b>EN:</b> Emthod set all fields from parameter <code>fields</code> to values
188 	 * set in this map. If field does not exist then method ignore this record.
189 	 * </p>
190 	 * 
191 	 * @param owner
192 	 *            obiekt na rzecz ktorego wykonywane jest ustawianie. <br/>
193 	 *            <b>EN:</b> Object which fields we set.
194 	 * @param fields
195 	 *            mapa pól. Kluczem jest wartość pola. <br/>
196 	 *            <b>EN:</b> map of fields and values. Keys are fields names.
197 	 */
198 	public static void setAll(final Object owner,
199 			final Map<String, Object> fields) {
200 		Field[] declaredFields = owner.getClass().getDeclaredFields();
201 		try {
202 			for (Field field : declaredFields) {
203 				Object fieldValue = fields.get(field.getName());
204 				if (fieldValue != null) {
205 					setPrivateField(field.getName(), owner, fieldValue, owner
206 							.getClass());
207 				}
208 			}
209 		} catch (NoSuchFieldException e) {
210 			throw new RuntimeException(e);
211 		}
212 	}
213 
214 	/**
215 	 * <p>
216 	 * Metoda podobna do {@link #setAll(Object, Map)}, ale ustawia wszystkie
217 	 * pola obiektu na <code>null</code>.
218 	 * </p>
219 	 * <p>
220 	 * <b>EN:</b> Set all fields to <code>null</code>.
221 	 * </p>
222 	 * 
223 	 * @param owner
224 	 *            obiekt, którego pola są ustawiane na <code>null</code>. <br/>
225 	 *            <b>EN:</b> Object which fields we set.
226 	 */
227 	public static void nullAll(final Object owner) {
228 		Field[] declaredFields = owner.getClass().getDeclaredFields();
229 		try {
230 			for (Field field : declaredFields) {
231 				setPrivateField(field.getName(), owner, null, owner.getClass());
232 			}
233 		} catch (NoSuchFieldException e) {
234 			throw new RuntimeException(e);
235 		}
236 	}
237 }