All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.powermock.reflect.Whitebox Maven / Gradle / Ivy

There is a newer version: 2.0.9
Show newest version
/*
 * Copyright 2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.powermock.reflect;

import org.powermock.reflect.exceptions.ConstructorNotFoundException;
import org.powermock.reflect.exceptions.FieldNotFoundException;
import org.powermock.reflect.exceptions.MethodNotFoundException;
import org.powermock.reflect.exceptions.TooManyMethodsFoundException;
import org.powermock.reflect.internal.WhiteboxImpl;
import org.powermock.reflect.matching.FieldMatchingStrategy;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Set;

/**
 * Various utilities for accessing internals of a class. Basically a simplified
 * reflection utility intended for tests.
 */
public class Whitebox {

	/**
	 * Convenience method to get a field from a class type.
	 * 

* The method will first try to look for a declared field in the same class. * If the field is not declared in this class it will look for the field in * the super class. This will continue throughout the whole class hierarchy. * If the field is not found an {@link IllegalArgumentException} is thrown. * * @param type * The type of the class where the method is located. * @param fieldName * The method names. * @return A {@code java.lang.reflect.Field}. * @throws FieldNotFoundException * If a field cannot be found in the hierarchy. */ public static Field getField(Class type, String fieldName) { return WhiteboxImpl.getField(type, fieldName); } /** * Get an array of {@link Field}'s that matches the supplied list of field * names. * * @param clazz * The class that should contain the fields. * @param fieldNames * The names of the fields that will be returned. * @return An array of Field's. May be of length 0 but not {@code null} * */ public static Field[] getFields(Class clazz, String... fieldNames) { return WhiteboxImpl.getFields(clazz, fieldNames); } /** * Convenience method to get a method from a class type without having to * catch the checked exceptions otherwise required. These exceptions are * wrapped as runtime exceptions. *

* The method will first try to look for a declared method in the same * class. If the method is not declared in this class it will look for the * method in the super class. This will continue throughout the whole class * hierarchy. If the method is not found an {@link IllegalArgumentException} * is thrown. * * @param type * The type of the class where the method is located. * @param methodName * The method names. * @param parameterTypes * All parameter types of the method (may be {@code null}). * @return A {@code java.lang.reflect.Method}. * @throws MethodNotFoundException * If a method cannot be found in the hierarchy. */ public static Method getMethod(Class type, String methodName, Class... parameterTypes) { return WhiteboxImpl.getMethod(type, methodName, parameterTypes); } /** * Convenience method to get a method from a class type without having to * catch the checked exceptions otherwise required. These exceptions are * wrapped as runtime exceptions. *

* The method will first try to look for a declared method in the same * class. If the method is not declared in this class it will look for the * method in the super class. This will continue throughout the whole class * hierarchy. If the method is not found an {@link MethodNotFoundException} * is thrown. Since the method name is not specified an * {@link TooManyMethodsFoundException} is thrown if two or more methods * matches the same parameter types in the same class. * * @param type * The type of the class where the method is located. * @param parameterTypes * All parameter types of the method (may be {@code null}). * @return A {@code java.lang.reflect.Method}. * @throws MethodNotFoundException * If a method cannot be found in the hierarchy. * @throws TooManyMethodsFoundException * If several methods were found. */ public static Method getMethod(Class type, Class... parameterTypes) { return WhiteboxImpl.getMethod(type, parameterTypes); } /** * Create a new instance of a class without invoking its constructor. *

* No byte-code manipulation is needed to perform this operation and thus * it's not necessary use the {@code PowerMockRunner} or * {@code PrepareForTest} annotation to use this functionality. * * @param * The type of the instance to create. * @param classToInstantiate * The type of the instance to create. * @return A new instance of type T, created without invoking the * constructor. */ public static T newInstance(Class classToInstantiate) { return WhiteboxImpl.newInstance(classToInstantiate); } /** * Convenience method to get a (declared) constructor from a class type * without having to catch the checked exceptions otherwise required. These * exceptions are wrapped as runtime exceptions. The constructor is also set * to accessible. * * @param type * The type of the class where the constructor is located. * @param parameterTypes * All parameter types of the constructor (may be * {@code null}). * @return A {@code java.lang.reflect.Constructor}. * @throws ConstructorNotFoundException * if the constructor cannot be found. */ public static Constructor getConstructor(Class type, Class... parameterTypes) { return (Constructor) WhiteboxImpl.getConstructor(type, parameterTypes); } /** * Set the value of a field using reflection. This method will traverse the * super class hierarchy until a field with name fieldName is * found. * * @param object * the object whose field to modify * @param fieldName * the name of the field * @param value * the new value of the field */ public static void setInternalState(Object object, String fieldName, Object value) { WhiteboxImpl.setInternalState(object, fieldName, value); } /** * Set an array value of a field using reflection. This method will traverse * the super class hierarchy until a field with name fieldName is * found. * * @param object * the object to modify * @param fieldName * the name of the field * @param value * the new value of the field */ public static void setInternalState(Object object, String fieldName, Object[] value) { WhiteboxImpl.setInternalState(object, fieldName, value); } /** * Set the value of a field using reflection. This method will traverse the * super class hierarchy until the first field assignable to the * value type is found. The value (or * additionaValues if present) will then be assigned to this field. * * @param object * the object to modify * @param value * the new value of the field * @param additionalValues * Additional values to set on the object */ public static void setInternalState(Object object, Object value, Object... additionalValues) { WhiteboxImpl.setInternalState(object, value, additionalValues); } /** * Set the value of a field using reflection at at specific place in the * class hierarchy (where). This first field assignable to * object will then be set to value. * * @param object * the object to modify * @param value * the new value of the field * @param where * the class in the hierarchy where the field is defined */ public static void setInternalState(Object object, Object value, Class where) { WhiteboxImpl.setInternalState(object, value, where); } /** * Set the value of a field using reflection. Use this method when you need * to specify in which class the field is declared. This might be useful * when you have mocked the instance you are trying to modify. * * @param object * the object to modify * @param fieldName * the name of the field * @param value * the new value of the field * @param where * the class in the hierarchy where the field is defined */ public static void setInternalState(Object object, String fieldName, Object value, Class where) { WhiteboxImpl.setInternalState(object, fieldName, value, where); } /** * Set the value of a field using reflection. This method will traverse the * super class hierarchy until the first field of type fieldType is * found. The value will then be assigned to this field. * * @param object * the object to modify * @param fieldType * the type of the field * @param value * the new value of the field */ public static void setInternalState(Object object, Class fieldType, Object value) { WhiteboxImpl.setInternalState(object, fieldType, value); } /** * Set the value of a field using reflection at a specific location ( * where) in the class hierarchy. The value will then be * assigned to this field. The first field matching the fieldType * in the hierarchy will be set. * * @param object * the object to modify * @param fieldType * the type of the field the should be set. * @param value * the new value of the field * @param where * which class in the hierarchy defining the field */ public static void setInternalState(Object object, Class fieldType, Object value, Class where) { WhiteboxImpl.setInternalState(object, fieldType, value, where); } /** * Get the value of a field using reflection. This method will iterate * through the entire class hierarchy and return the value of the first * field named fieldName. If you want to get a specific field value * at specific place in the class hierarchy please refer to * {@link #getInternalState(Object, String, Class)}. * * @param object * the object to modify * @param fieldName * the name of the field */ public static T getInternalState(Object object, String fieldName) { return WhiteboxImpl.getInternalState(object, fieldName); } /** * Get the value of a field using reflection. Use this method when you need * to specify in which class the field is declared. This might be useful * when you have mocked the instance you are trying to access. * * @param object * the object to modify * @param fieldName * the name of the field * @param where * which class the field is defined */ public static T getInternalState(Object object, String fieldName, Class where) { return WhiteboxImpl.getInternalState(object, fieldName, where); } /** * Get the value of a field using reflection. Use this method when you need * to specify in which class the field is declared. This might be useful * when you have mocked the instance you are trying to access. Use this * method to avoid casting. * * @deprecated Use {@link #getInternalState(Object, String, Class)} instead. * * @param * the expected type of the field * @param object * the object to modify * @param fieldName * the name of the field * @param where * which class the field is defined * @param type * the expected type of the field */ @Deprecated public static T getInternalState(Object object, String fieldName, Class where, Class type) { return Whitebox.getInternalState(object, fieldName, where); } /** * Get the value of a field using reflection based on the fields type. This * method will traverse the super class hierarchy until the first field of * type fieldType is found. The value of this field will be * returned. * * @param object * the object to modify * @param fieldType * the type of the field */ public static T getInternalState(Object object, Class fieldType) { return WhiteboxImpl.getInternalState(object, fieldType); } /** * Get the value of a field using reflection based on the field type. Use * this method when you need to specify in which class the field is * declared. The first field matching the fieldType in * where is the field whose value will be returned. * * @param * the expected type of the field * @param object * the object to modify * @param fieldType * the type of the field * @param where * which class the field is defined */ public static T getInternalState(Object object, Class fieldType, Class where) { return WhiteboxImpl.getInternalState(object, fieldType, where); } /** * Invoke a private or inner class method without the need to specify the * method name. This is thus a more refactor friendly version of the * {@link #invokeMethod(Object, String, Object...)} method and is recommend * over this method for that reason. This method might be useful to test * private methods. * * @throws Exception if something wrong. */ public static synchronized T invokeMethod(Object instance, Object... arguments) throws Exception { return WhiteboxImpl.invokeMethod(instance, arguments); } /** * Invoke a private or inner class static method without the need to specify * the method name. This is thus a more refactor friendly version of the * {@link #invokeMethod(Class, String, Object...)} method and is recommend * over this method for that reason. This method might be useful to test * private methods. * */ public static synchronized T invokeMethod(Class klass, Object... arguments) throws Exception { return WhiteboxImpl.invokeMethod(klass, arguments); } /** * Invoke a private or inner class method. This might be useful to test * private methods. */ public static synchronized T invokeMethod(Object instance, String methodToExecute, Object... arguments) throws Exception { return WhiteboxImpl.invokeMethod(instance, methodToExecute, arguments); } /** * Invoke a private or inner class method in cases where PowerMock cannot * automatically determine the type of the parameters, for example when * mixing primitive types and wrapper types in the same method. For most * situations use {@link #invokeMethod(Object, Object...)} instead. * * @throws Exception * Exception that may occur when invoking this method. */ public static synchronized T invokeMethod(Object instance, String methodToExecute, Class[] argumentTypes, Object... arguments) throws Exception { return WhiteboxImpl.invokeMethod(instance, methodToExecute, argumentTypes, arguments); } /** * Invoke a private or inner class method in a subclass (defined by * {@code definedIn}) in cases where PowerMock cannot automatically * determine the type of the parameters, for example when mixing primitive * types and wrapper types in the same method. For most situations use * {@link #invokeMethod(Object, Object...)} instead. * * @throws Exception * Exception that may occur when invoking this method. */ public static synchronized T invokeMethod(Object instance, String methodToExecute, Class definedIn, Class[] argumentTypes, Object... arguments) throws Exception { return WhiteboxImpl.invokeMethod(instance, methodToExecute, definedIn, argumentTypes, arguments); } /** * Invoke a private or inner class method in that is located in a subclass * of the instance. This might be useful to test private methods. * * @throws Exception * Exception that may occur when invoking this method. */ public static synchronized T invokeMethod(Object instance, Class declaringClass, String methodToExecute, Object... arguments) throws Exception { return WhiteboxImpl.invokeMethod(instance, declaringClass, methodToExecute, arguments); } /** * Invoke a private or inner class method in that is located in a subclass * of the instance. This might be useful to test private methods. *

* Use this for overloaded methods. * * @throws Exception * Exception that may occur when invoking this method. */ public static synchronized T invokeMethod(Object object, Class declaringClass, String methodToExecute, Class[] parameterTypes, Object... arguments) throws Exception { return WhiteboxImpl.invokeMethod(object, declaringClass, methodToExecute, parameterTypes, arguments); } /** * Invoke a static private or inner class method. This may be useful to test * private methods. * */ public static synchronized T invokeMethod(Class clazz, String methodToExecute, Object... arguments) throws Exception { return WhiteboxImpl.invokeMethod(clazz, methodToExecute, arguments); } /** * Invoke a constructor. Useful for testing classes with a private * constructor when PowerMock cannot determine which constructor to invoke. * This only happens if you have two constructors with the same number of * arguments where one is using primitive data types and the other is using * the wrapped counter part. For example: * *

	 * public class MyClass {
	 *     private MyClass(Integer i) {
	 *         ...
	 *     } 
	 * 
	 *     private MyClass(int i) {
	 *         ...
	 *     }
	 * 
* * This ought to be a really rare case. So for most situation, use * {@link #invokeConstructor(Class, Object...)} instead. * * * @return The object created after the constructor has been invoked. * @throws Exception * If an exception occur when invoking the constructor. */ public static T invokeConstructor(Class classThatContainsTheConstructorToTest, Class[] parameterTypes, Object[] arguments) throws Exception { return WhiteboxImpl.invokeConstructor(classThatContainsTheConstructorToTest, parameterTypes, arguments); } /** * Invoke a constructor. Useful for testing classes with a private * constructor. * * * @return The object created after the constructor has been invoked. * @throws Exception * If an exception occur when invoking the constructor. */ public static T invokeConstructor(Class classThatContainsTheConstructorToTest, Object... arguments) throws Exception { return WhiteboxImpl.invokeConstructor(classThatContainsTheConstructorToTest, arguments); } /** * Get the first parent constructor defined in a super class of * {@code klass}. * * @param klass * The class where the constructor is located. {@code null} * ). * @return A {@code java.lang.reflect.Constructor}. */ public static Constructor getFirstParentConstructor(Class klass) { return WhiteboxImpl.getFirstParentConstructor(klass); } /** * Get an array of {@link Method}'s that matches the supplied list of method * names. Both instance and static methods are taken into account. * * @param clazz * The class that should contain the methods. * @param methodNames * Names of the methods that will be returned. * @return An array of Method's. * @throws MethodNotFoundException * If no method was found. */ public static Method[] getMethods(Class clazz, String... methodNames) { return WhiteboxImpl.getMethods(clazz, methodNames); } /** * @return The type of the of an object. */ public static Class getType(Object object) { return WhiteboxImpl.getType(object); } /** * Gets the type. * * @param object the object * @return The type of the of an object. */ public static Class getUnproxyType(Object object) { return WhiteboxImpl.getUnproxyType(object); } /** * Get all fields annotated with a particular annotation. This method * traverses the class hierarchy when checking for the annotation. * * @param object * The object to look for annotations. Note that if're you're * passing an object only instance fields are checked, passing a * class will only check static fields. * @param annotation * The annotation type to look for. * @param additionalAnnotations * Optionally more annotations to look for. If any of the * annotations are associated with a particular field it will be * added to the resulting {@code Set}. * @return A set of all fields containing the particular annotation. */ public static Set getFieldsAnnotatedWith(Object object, Class annotation, Class... additionalAnnotations) { return WhiteboxImpl.getFieldsAnnotatedWith(object, annotation, additionalAnnotations); } /** * Get all fields annotated with a particular annotation. This method * traverses the class hierarchy when checking for the annotation. * * @param object * The object to look for annotations. Note that if're you're * passing an object only instance fields are checked, passing a * class will only check static fields. * @param annotationTypes * The annotation types to look for * @return A set of all fields containing the particular annotation(s). * @since 1.3 */ public static Set getFieldsAnnotatedWith(Object object, Class[] annotationTypes) { return WhiteboxImpl.getFieldsAnnotatedWith(object, annotationTypes); } /** * Get all instance fields for a particular object. It returns all fields * regardless of the field modifier and regardless of where in the class * hierarchy a field is located. * * @param object * The object whose instance fields to get. * @return All instance fields in the hierarchy. All fields are set to * accessible */ public static Set getAllInstanceFields(Object object) { return WhiteboxImpl.getAllInstanceFields(object); } /** * Get all static fields for a particular type. * * @param type * The class whose static fields to get. * @return All static fields in {@code type}. All fields are set to * accessible. */ public static Set getAllStaticFields(Class type) { return WhiteboxImpl.getAllStaticFields(type); } /** * Get all fields assignable from a particular type. This method traverses * the class hierarchy when checking for the type. * * @param object * The object to look for type. Note that if're you're passing an * object only instance fields are checked, passing a class will * only check static fields. * @param type * The type to look for. * @return A set of all fields of the particular type. */ public static Set getFieldsOfType(Object object, Class type) { return WhiteboxImpl.getFieldsOfType(object, type); } /** * Get an inner class type * * @param declaringClass * The class in which the inner class is declared. * @param name * The unqualified name (simple name) of the inner class. * @return The type. */ public static Class getInnerClassType(Class declaringClass, String name) throws ClassNotFoundException { return WhiteboxImpl.getInnerClassType(declaringClass, name); } /** * Get the type of a local inner class. * * @param declaringClass * The class in which the local inner class is declared. * @param occurrence * The occurrence of the local class. For example if you have two * local classes in the {@code declaringClass} you must pass * in {@code 1} if you want to get the type for the first * one or {@code 2} if you want the second one. * @param name * The unqualified name (simple name) of the local class. * @return The type. */ public static Class getLocalClassType(Class declaringClass, int occurrence, String name) throws ClassNotFoundException { return WhiteboxImpl.getLocalClassType(declaringClass, occurrence, name); } /** * Get the type of an anonymous inner class. * * @param declaringClass * The class in which the anonymous inner class is declared. * @param occurrence * The occurrence of the anonymous inner class. For example if * you have two anonymous inner classes classes in the * {@code declaringClass} you must pass in {@code 1} if * you want to get the type for the first one or {@code 2} * if you want the second one. * @return The type. */ public static Class getAnonymousInnerClassType(Class declaringClass, int occurrence) throws ClassNotFoundException { return WhiteboxImpl.getAnonymousInnerClassType(declaringClass, occurrence); } /** * Set the values of multiple instance fields defined in a context using * reflection. The values in the context will be assigned to values on the * {@code instance}. This method will traverse the class hierarchy when * searching for the fields. Example usage: *

* Given: * *

	 * public class MyContext {
	 * 	private String myString = "myString";
	 * 	protected int myInt = 9;
	 * }
	 * 
	 * public class MyInstance {
	 * 	private String myInstanceString;
	 * 	private int myInstanceInt;
	 * 
	 * }
	 * 
* * then * *
	 * Whitebox.setInternalStateFromContext(new MyInstance(), new MyContext());
	 * 
* * will set the instance variables of {@code myInstance} to the values * specified in {@code MyContext}. *

* By default the {@link FieldMatchingStrategy#MATCHING} strategy is used * which means that the fields defined in the context but not found in the * classOrInstance are silently ignored. * * * * @param instance * the object whose fields to modify. * @param context * The context where the fields are defined. * @param additionalContexts * Optionally more additional contexts. */ public static void setInternalStateFromContext(Object instance, Object context, Object... additionalContexts) { WhiteboxImpl.setInternalStateFromContext(instance, context, additionalContexts); } /** * Set the values of multiple static fields defined in a context using * reflection. The values in the context will be assigned to values on the * {@code classOrInstance}. This method will traverse the class * hierarchy when searching for the fields. Example usage: *

* Given: * *

	 * public class MyContext {
	 * 	private static String myString = "myString";
	 * 	protected static int myInt = 9;
	 * }
	 * 
	 * public class MyInstance {
	 * 	private static String myInstanceString;
	 * 	private static int myInstanceInt;
	 * 
	 * }
	 * 
* * then * *
	 * Whitebox.setInternalStateFromContext(MyInstance.class, MyContext.class);
	 * 
* * will set the static variables of {@code MyInstance} to the values * specified in {@code MyContext}. *

* By default the {@link FieldMatchingStrategy#MATCHING} strategy is used * which means that the fields defined in the context but not found in the * classOrInstance are silently ignored. * * @param classOrInstance * The object or class whose fields to set. * @param context * The context where the fields are defined. * @param additionalContexts * Optionally more additional contexts. */ public static void setInternalStateFromContext(Object classOrInstance, Class context, Class... additionalContexts) { WhiteboxImpl.setInternalStateFromContext(classOrInstance, context, additionalContexts); } /** * Set the values of multiple instance fields defined in a context using * reflection and using an explicit {@link FieldMatchingStrategy}. The * values in the context will be assigned to values on the * {@code instance}. This method will traverse the class hierarchy when * searching for the fields. Example usage: *

* Given: * *

	 * public class MyContext {
	 * 	private String myString = "myString";
	 * 	protected int myInt = 9;
	 * }
	 * 
	 * public class MyInstance {
	 * 	private String myInstanceString;
	 * 	private int myInstanceInt;
	 * 
	 * }
	 * 
* * then * *
	 * Whitebox.setInternalStateFromContext(new MyInstance(), new MyContext());
	 * 
* * will set the instance variables of {@code myInstance} to the values * specified in {@code MyContext}. * * @param instance * the object whose fields to modify. * @param context * The context where the fields are defined. * @param strategy * Which field matching strategy to use. */ public static void setInternalStateFromContext(Object instance, Object context, FieldMatchingStrategy strategy) { WhiteboxImpl.setInternalStateFromContext(instance, context, strategy); } /** * Set the values of multiple static fields defined in a context using * reflection and using an explicit {@link FieldMatchingStrategy}. The * values in the context will be assigned to values on the * {@code classOrInstance}. This method will traverse the class * hierarchy when searching for the fields. Example usage: *

* Given: * *

	 * public class MyContext {
	 * 	private static String myString = "myString";
	 * 	protected static int myInt = 9;
	 * }
	 * 
	 * public class MyInstance {
	 * 	private static String myInstanceString;
	 * 	private static int myInstanceInt;
	 * 
	 * }
	 * 
* * then * *
	 * Whitebox.setInternalStateFromContext(MyInstance.class, MyContext.class);
	 * 
* * will set the static variables of {@code MyInstance} to the values * specified in {@code MyContext}. *

* * @param instance * The object or class whose fields to set. * @param context * The context where the fields are defined. * @param strategy * Which field matching strategy to use. */ public static void setInternalStateFromContext(Object instance, Class context, FieldMatchingStrategy strategy) { WhiteboxImpl.setInternalStateFromContext(instance, context, strategy); } public static Object getFieldValue(final Field field, final Object object) { return WhiteboxImpl.getFieldValue(field, object); } }