CS 1705 Library

net.sf.webcat
Class ReflectionSupport

java.lang.Object
  extended by net.sf.webcat.ReflectionSupport

public class ReflectionSupport
extends Object

This class provides static helper methods to use reflection to check for and invoke methods on objects. It is intended for use in test cases, and makes it easier to write test cases that compile successfully but fail at run-time if the class under test fails to provide required methods (or provides them with the wrong signature). For Web-CAT users, this makes it possible to get partial scores, even when some methods are not even provided in the class under test.

Consider a situation where you are writing a test case that invokes the doIt() method on a given object. You might do it like this:

  MyType result = receiver.doIt(param1, param2);  // returns a value
  // ...
  receiver.doSomethingElse();  // a void method with no parameters
  

The first line passes two parameters to doIt() and stores the return value in a local variable called result. All this would be fine if the class under test actually provides a method called doIt() with the appropriate signature and return type. Otherwise, you would get a compile-time error. But on Web-CAT a compilation error in a test suite would give a resulting score of zero--no successful compilation, no partial credit. The story is similar with the second line, which simply calls a void method on the class under test.

What if, instead, you wanted to write test cases that checked for specific methods, and either succeeded or failed depending on whether the method was present? You can use the methods in this class to write such test cases. So instead of writing the call above, you could do this:

  // At the top of your test class
  import static net.sf.webcat.ReflectionSupport.*;

  // ...

  // For a method that returns a result:
  MyType result = invoke(receiver, MyType.class, "doIt", param1, param2);

  // Or for a void method:
  invoke(receiver, "doSomethingElse");
  

The syntax is simple and straight forward. The overloaded invoke method can be used on functions (methods that return a value) or procedures (void methods that return nothing). For methods that return a value, you specify the type of the return value as the second parameter. If you omit the return type, then it is assumed to be "void". You specify the name of the method as a string, and then a variable length set of arguments.

If you are calling a method that is returning a primitive type, be sure to use the corresponding wrapper class as the expected return value:

  // Instead of boolean answer = receiver.equals(anotherObject);
  Boolean answer = invoke(receiver, Boolean.class, "equals", anotherObject);

  // Or in an assert, using auto-unboxing:
  assertTrue(invoke(receiver, Boolean.class, "equals", anotherObject));
  

Any errors that occur during reflection, such as failing to find the required method, failing to find a method with the required signature, finding a method that is not public, etc., are converted into appropriate test case errors with meaningful diagnostic hints for the student. Any exceptions are wrapped in a RuntimeException and need not be explicitly caught by the caller (they will turn into test case failures as well).

Version:
$Id: ReflectionSupport.java,v 1.4 2007/10/19 17:05:42 stedwar2 Exp $
Author:
stedwar2

Method Summary
static boolean actualMatchesFormal(Class<?> actual, Class<?> formal)
          Determine whether an actual argument type matches a formal argument type.
static
<T> T
create(Class<T> returnType, Object... params)
          Dynamically look up and invoke a class constructor for the target class, with appropriate hints if any failures happen along the way.
static Object create(Constructor<?> constructor, Object... params)
          Just like Constructor.newInstance(Object...), but converts any thrown exceptions into RuntimeExceptions.
static Object create(String className, Object... params)
          Dynamically look up and invoke a class constructor for the target class, with appropriate hints if any failures happen along the way.
static
<T> T
createEx(Class<T> returnType, Object... params)
          Just like #create(Class, Object...), but unwraps any InvocationTargetExceptions and throws the true cause.
static Object createEx(Constructor<?> constructor, Object... params)
          Just like create(Constructor, Object...), but unwraps any InvocationTargetExceptions and throws the true cause.
static Object createEx(String className, Object... params)
          Just like create(String, Object...), but unwraps any InvocationTargetExceptions and throws the true cause.
static Class<?> getClassForName(String className)
          Dynamically look up a class by name, with appropriate hints if the class cannot be found.
static Constructor<?> getMatchingConstructor(Class<?> c, Class<?>... params)
          Look up a constructor by parameter profile, finding the constructor that will accept the given list of parameters (not requiring an exact match on parameter types).
static Method getMatchingMethod(Class<?> c, String name, Class<?>... params)
          Look up a method by name and parameter profile, finding the method that will accept the given list of parameters (not requiring an exact match on parameter types).
static Method getMethod(Class<?> c, String name, Class<?>... params)
          Look up a method by name and parameter profile, turning any errors into test case failures with appropriate hint messages.
static
<T> T
invoke(Object receiver, Class<T> returnType, String methodName, Object... params)
          Dynamically look up and invoke a method on a target object, with appropriate hints if any failures happen along the way.
static Object invoke(Object receiver, Method method, Object... params)
          Just like Method.invoke(Object, Object...), but converts any thrown exceptions into RuntimeExceptions.
static void invoke(Object receiver, String methodName, Object... params)
          Dynamically look up and invoke a method on a target object, with appropriate hints if any failures happen along the way.
static
<T> T
invokeEx(Object receiver, Class<T> returnType, String methodName, Object... params)
          Just like #invoke(Object, Class, Object...), but unwraps any InvocationTargetExceptions and throws the true cause.
static Object invokeEx(Object receiver, Method method, Object... params)
          Just like Method.invoke(Object, Object...), but unwraps any InvocationTargetExceptions and throws the true cause.
static void invokeEx(Object receiver, String methodName, Object... params)
          Just like invoke(Object, String, Object...), but unwraps any InvocationTargetExceptions and throws the true cause.
static String simpleArgumentList(Class<?>... params)
          Constructs a printable version of a method's argument list, including the parentheses, given the method's parameter type(s), if any.
static String simpleClassName(Class<?> aClass)
          Returns the name of the given class without any package prefix.
static String simpleMethodName(Method method)
          Constructs a printable version of a method's name.
static String simpleMethodName(String name, Class<?>... params)
          Constructs a printable version of a method's name, given the method name and its parameter type(s), if any.
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Method Detail

simpleClassName

public static String simpleClassName(Class<?> aClass)
Returns the name of the given class without any package prefix. If the argument is an array type, square brackets are added to the name as appropriate. This method isuseful in generating diagnostic messages or feedback.

Parameters:
aClass - The class to generate a name for
Returns:
The class' name, without the package part, e.g., "String" instead of "java.lang.String"

simpleMethodName

public static String simpleMethodName(String name,
                                      Class<?>... params)
Constructs a printable version of a method's name, given the method name and its parameter type(s), if any. Useful in generating diagnostic messages or feedback.

Parameters:
name - The method name
params - The method's parameter type(s), in order
Returns:
A printable version of the method name, like "myMethod()" or "yourMethod(String, int)"

simpleArgumentList

public static String simpleArgumentList(Class<?>... params)
Constructs a printable version of a method's argument list, including the parentheses, given the method's parameter type(s), if any.

Parameters:
params - The method's parameter type(s), in order
Returns:
A printable version of the argument list built using simpleClassName(Class), like "(String, int)"

simpleMethodName

public static String simpleMethodName(Method method)
Constructs a printable version of a method's name. Unlike Method.toString(), this one uses simpleClassName(Class) so package info is eliminated from the types in the resulting string. It also omits exception information, unlike Method.toString().

Parameters:
method - The method to print
Returns:
A printable version of the method name, like "public void MyClass.myMethod()" or "public String YourClass.yourMethod(String, int)"

actualMatchesFormal

public static boolean actualMatchesFormal(Class<?> actual,
                                          Class<?> formal)
Determine whether an actual argument type matches a formal argument type. This uses Class.isAssignableFrom(Class), but gives the correct results for primitive types vs. wrapper types.

Parameters:
actual - The type of the actual parameter
formal - The type of the formal parameter
Returns:
True if the actual value can be passed into a parameter declared using the formal type

getMethod

public static Method getMethod(Class<?> c,
                               String name,
                               Class<?>... params)
Look up a method by name and parameter profile, turning any errors into test case failures with appropriate hint messages. Only looks up methods that are declared in the specified class, not inherited methods. Assumes the intended method should be public, and fails with an appropriate hint if it is not.

Parameters:
c - The type of the receiver
name - The method name
params - The method's parameter profile
Returns:
The corresponding Method object

getMatchingMethod

public static Method getMatchingMethod(Class<?> c,
                                       String name,
                                       Class<?>... params)
Look up a method by name and parameter profile, finding the method that will accept the given list of parameters (not requiring an exact match on parameter types). It turns any errors into test case failures with appropriate hint messages. Only looks up methods that are declared in the specified class, not inherited methods. Assumes the intended method should be public, and fails with an appropriate hint if it is not. Note that this method does not handle variable argument lists in the target method for which it is searching.

Parameters:
c - The type of the receiver
name - The method name
params - The method's parameter profile
Returns:
The corresponding Method object

invoke

public static <T> T invoke(Object receiver,
                           Class<T> returnType,
                           String methodName,
                           Object... params)
Dynamically look up and invoke a method on a target object, with appropriate hints if any failures happen along the way.

Type Parameters:
T - The generic parameter T is deduced from the returnType
Parameters:
receiver - The object to invoke the method on
returnType - The expected type of the method's return value. Use null (or void.class) if the method that is looked up is a void method.
methodName - The name of the method to invoke
params - The parameters to pass to the method
Returns:
The results from invoking the given method

invoke

public static void invoke(Object receiver,
                          String methodName,
                          Object... params)
Dynamically look up and invoke a method on a target object, with appropriate hints if any failures happen along the way. This version is intended for calling "void" methods that have no return value.

Parameters:
receiver - The object to invoke the method on
methodName - The name of the method to invoke
params - The parameters to pass to the method

invoke

public static Object invoke(Object receiver,
                            Method method,
                            Object... params)
Just like Method.invoke(Object, Object...), but converts any thrown exceptions into RuntimeExceptions.

Parameters:
receiver - The object to invoke the method on
method - The method to invoke
params - The parameters to pass to the method
Returns:
The result from the method

invokeEx

public static <T> T invokeEx(Object receiver,
                             Class<T> returnType,
                             String methodName,
                             Object... params)
                  throws Exception
Just like #invoke(Object, Class, Object...), but unwraps any InvocationTargetExceptions and throws the true cause. This version is provided when you want to write test cases where you are intending to check for Exceptions as expected results.

Type Parameters:
T - The generic parameter T is deduced from the returnType
Parameters:
receiver - The object to invoke the method on
returnType - The expected type of the method's return value. Use null (or void.class) if the method that is looked up is a void method.
methodName - The name of the method to invoke
params - The parameters to pass to the method
Returns:
The results from invoking the given method
Throws:
Exception - if the underlying method throws one

invokeEx

public static void invokeEx(Object receiver,
                            String methodName,
                            Object... params)
                     throws Exception
Just like invoke(Object, String, Object...), but unwraps any InvocationTargetExceptions and throws the true cause. This version is provided when you want to write test cases where you are intending to check for Exceptions as expected results.

Parameters:
receiver - The object to invoke the method on
methodName - The name of the method to invoke
params - The parameters to pass to the method
Throws:
Exception - if the underlying method throws one

invokeEx

public static Object invokeEx(Object receiver,
                              Method method,
                              Object... params)
                       throws Exception
Just like Method.invoke(Object, Object...), but unwraps any InvocationTargetExceptions and throws the true cause. This version is provided when you want to write test cases where you are intending to check for Exceptions as expected results.

Parameters:
receiver - The object to invoke the method on
method - The method to invoke
params - The parameters to pass to the method
Returns:
The result from the method
Throws:
Exception - if the underlying method throws one

getMatchingConstructor

public static Constructor<?> getMatchingConstructor(Class<?> c,
                                                    Class<?>... params)
Look up a constructor by parameter profile, finding the constructor that will accept the given list of parameters (not requiring an exact match on parameter types). It turns any errors into test case failures with appropriate hint messages. Assumes the intended constructor should be public, and fails with an appropriate hint if it is not. Note that this method does not handle variable argument lists in the target constructor for which it is searching.

Parameters:
c - The type of object to create
params - The constructor's parameter profile
Returns:
The corresponding Constructor object

create

public static Object create(Constructor<?> constructor,
                            Object... params)
Just like Constructor.newInstance(Object...), but converts any thrown exceptions into RuntimeExceptions.

Parameters:
constructor - The constructor to invoke
params - The parameters to pass to the constructor
Returns:
The newly created object

create

public static <T> T create(Class<T> returnType,
                           Object... params)
Dynamically look up and invoke a class constructor for the target class, with appropriate hints if any failures happen along the way.

Type Parameters:
T - The generic parameter T is deduced from the returnType
Parameters:
returnType - The type of object to create.
params - The parameters to pass to the constructor
Returns:
The newly created object

create

public static Object create(String className,
                            Object... params)
Dynamically look up and invoke a class constructor for the target class, with appropriate hints if any failures happen along the way.

Parameters:
className - The type of object to create
params - The parameters to pass to the constructor
Returns:
The newly created object

createEx

public static Object createEx(Constructor<?> constructor,
                              Object... params)
                       throws Exception
Just like create(Constructor, Object...), but unwraps any InvocationTargetExceptions and throws the true cause. This version is provided when you want to write test cases where you are intending to check for Exceptions as expected results.

Parameters:
constructor - The constructor to invoke
params - The parameters to pass to the constructor
Returns:
The newly created object
Throws:
Exception - if the underlying method throws one

createEx

public static <T> T createEx(Class<T> returnType,
                             Object... params)
                  throws Exception
Just like #create(Class, Object...), but unwraps any InvocationTargetExceptions and throws the true cause. This version is provided when you want to write test cases where you are intending to check for Exceptions as expected results.

Type Parameters:
T - The generic parameter T is deduced from the returnType
Parameters:
returnType - The type of object to create.
params - The parameters to pass to the constructor
Returns:
The newly created object
Throws:
Exception - if the underlying method throws one

createEx

public static Object createEx(String className,
                              Object... params)
                       throws Exception
Just like create(String, Object...), but unwraps any InvocationTargetExceptions and throws the true cause. This version is provided when you want to write test cases where you are intending to check for Exceptions as expected results.

Parameters:
className - The type of object to create
params - The parameters to pass to the constructor
Returns:
The newly created object
Throws:
Exception - if the underlying method throws one

getClassForName

public static Class<?> getClassForName(String className)
Dynamically look up a class by name, with appropriate hints if the class cannot be found.

Parameters:
className - The type of object to create
Returns:
The corresponding Class object

Last updated: Wed, Apr 1, 2009 • 12:29 AM EDT

Copyright © 2009 Virginia Tech.