1414
1515package org.spockframework.util
1616
17+ import org.junit.platform.commons.annotation.Testable
1718import spock.lang.*
1819
20+ import java.lang.annotation.Annotation
21+ import java.lang.reflect.Method
22+
1923class ReflectionUtilSpec extends Specification {
2024 def " get package name" () {
2125 expect :
@@ -42,6 +46,7 @@ class ReflectionUtilSpec extends Specification {
4246 expect :
4347 ReflectionUtil . isMethodAvailable(" java.util.List" , " size" )
4448 ! ReflectionUtil . isMethodAvailable(" java.util.List" , " mice" )
49+ ! ReflectionUtil . isMethodAvailable(" not.AvailableClass" , " size" )
4550 }
4651
4752 def " check if annotation of certain type is present" () {
@@ -200,4 +205,126 @@ class ReflectionUtilSpec extends Specification {
200205 static class Generics <T> {
201206 void foo (T one , List<T> two , List<String > three ) {}
202207 }
208+
209+ def " isAnnotationPresentRecursive" (Class<?> clazz, Class<? extends Annotation > annotation, boolean expectedResult) {
210+ expect :
211+ ReflectionUtil . isAnnotationPresentRecursive(clazz, annotation) == expectedResult
212+ where :
213+ clazz | annotation | expectedResult
214+ Object | Nullable | false
215+ Specification | Testable | true
216+ ReflectionUtilSpec | Testable | true
217+ ReflectionUtilSpec | Nullable | false
218+ TypeWithAnno | Narrative | true
219+ SubTypeNoAnno | Narrative | true
220+ }
221+
222+ def " getAnnotationRecursive expecting annotation" (Class<?> clazz, Class<? extends Annotation > annotationClass) {
223+ when :
224+ def anno = ReflectionUtil . getAnnotationRecursive(clazz, annotationClass)
225+ then :
226+ clazz && annotationClass && anno != null
227+ where :
228+ clazz | annotationClass
229+ Specification | Testable
230+ ReflectionUtilSpec | Testable
231+ TypeWithAnno | Narrative
232+ SubTypeNoAnno | Narrative
233+ }
234+
235+ def " getAnnotationRecursive expecting none" (Class<?> clazz, Class<? extends Annotation > annotationClass) {
236+ when :
237+ def anno = ReflectionUtil . getAnnotationRecursive(clazz, annotationClass)
238+ then :
239+ clazz && annotationClass && anno == null
240+ where :
241+ clazz | annotationClass
242+ Object | Nullable
243+ ReflectionUtilSpec | Nullable
244+ }
245+
246+ def " collectAnnotationRecursive" (Class<?> clazz, Class<? extends Annotation > annotationClass, int expectedCount) {
247+ expect :
248+ ReflectionUtil . collectAnnotationRecursive(clazz, annotationClass). size() == expectedCount
249+ where :
250+ clazz | annotationClass | expectedCount
251+ Object | Nullable | 0
252+ Specification | Testable | 1
253+ ReflectionUtilSpec | Testable | 2
254+ ReflectionUtilSpec | Nullable | 0
255+ TypeWithAnno | Narrative | 1
256+ SubTypeNoAnno | Narrative | 1
257+ SubTypeWithAnno | Narrative | 2
258+ }
259+
260+ @Narrative
261+ private static class TypeWithAnno {}
262+
263+ @Narrative
264+ private static class SubTypeWithAnno extends TypeWithAnno {}
265+
266+ private static class SubTypeNoAnno extends TypeWithAnno {}
267+
268+ def " validateArguments - wrong argument count" () {
269+ when :
270+ ReflectionUtil . validateArguments(lookupMethod(" methodNoArgs" ), " Str" )
271+ then :
272+ IllegalArgumentException ex = thrown()
273+ ex. message == " Method 'methodNoArgs([])' can't be called with parameters '[Str]'!"
274+ }
275+
276+ def " validateArguments - incompatible type" () {
277+ when : " Incompatible type"
278+ ReflectionUtil . validateArguments(lookupMethod(" methodOneArg" ), 1 )
279+ then :
280+ IllegalArgumentException ex = thrown()
281+ ex. message == " Method 'methodOneArg([class java.lang.String])' can't be called with parameters '[1]'!"
282+ }
283+
284+ def " validateArguments - null value on primitive type" () {
285+ when : " Null value on primitive type"
286+ ReflectionUtil . validateArguments(lookupMethod(" methodPrimitiveArg" ), [null ] as Object [])
287+ then :
288+ thrown(IllegalArgumentException )
289+ }
290+
291+ def " validateArguments - Correct types" () {
292+ when : " Correct types"
293+ ReflectionUtil . validateArguments(lookupMethod(" methodOneArg" ), " Str" )
294+ then :
295+ noExceptionThrown()
296+ }
297+
298+ private Method lookupMethod (String name ) {
299+ return Objects . requireNonNull(ReflectionUtilSpec . class. getMethods(). find { it. name == name })
300+ }
301+
302+ @SuppressWarnings (' unused' )
303+ static void methodNoArgs () {}
304+
305+ @SuppressWarnings (' unused' )
306+ static void methodOneArg (String s ) {}
307+
308+ @SuppressWarnings (' unused' )
309+ static void methodPrimitiveArg (int value ) {}
310+
311+ def " deepCopyFields errors" () {
312+ when :
313+ ReflectionUtil . deepCopyFields(" Str" , 10 )
314+ then :
315+ IllegalArgumentException ex = thrown()
316+ ex. message == " source and target are not compatible."
317+ }
318+
319+ def " getClassFile" () {
320+ expect :
321+ ReflectionUtil . getClassFile(String ) == null
322+ ReflectionUtil . getClassFile(Specification ) == null
323+ ReflectionUtil . getClassFile(ReflectionUtilSpec ) != null
324+ }
325+
326+ def " isToStringOverridden error" () {
327+ expect :
328+ ! ReflectionUtil . isToStringOverridden(int . class)
329+ }
203330}
0 commit comments