View on GitHub

Privileged Accessor

PrivilegedAccessor is a simple to use Java framework for accessing private methods, attributes, and constructors via reflection.

Download this project as a .zip file Download this project as a tar.gz file

PrivilegedAccessor is a simple to use Java framework for accessing private methods, attributes, and constructors via reflection.

Introduction

In unit-testing you often need to prepare and later inspect the unit-under-test before you can test it. For instance you might need to inject mock-objects in your unit, so your unit-test does not access other units like backend systems. Or you might need to access a private attribute to assert a post-condition of a unit after the test.

This could be easily done if Java had no modifiers like private. Accessing private (or protected or package private) methods, attributes, and constructors from outside is forbidden. And you should never change the modifiers of your production code just for unit-testing purposes!!!

Fortunately we have reflection to access everything in our classes. Unfortunately reflection is somehow complicated:

Example: Accessing the private (float) field salary of the object boss of class Manager via reflection:

try {
  Field field = Manager.class.getDeclaredField(salary);
  field.setAccessible(true);
  float howMuchMyBossEarns = (float) field.get(boss);
} catch (NoSuchFieldException e) {
  assert false: "class 'Manager' has no field 'salary'";
} catch (IllegalAccessException e) {
  assert false : "could not access field 'salary'";
  return null;
}

With PrivilegedAccessor the same task is much less work:

float howMuchMyBossEarns = PA.getValue(boss, "salary");

Download

You can download PrivilegedAccessor via Downloads or from maven central using:

<dependency>
  <groupId>com.e-movimento.tinytools</groupId>
  <artifactId>privilegedaccessor</artifactId>
  <version>1.3</version>
</dependency>

How does it work

PrivilegedAccessor is based on Java reflection and the possibility to change access-rights via "setAccessible(true)". PrivilegedAccessor tries to find the method, attribute, constructor you want to access, sets its accessibility to true and accesses it.

Usage

The usage of PrivilegedAccessor is rather simple. Use the following to access your otherwise unaccessible code:

PA (the convenience short form for PrivilegedAccessor) works with varargs and autoboxing and only throws RuntimeExceptions.

Examples

PA.getValue(myObject, "myAttribute");
PA.setValue(myObject, "myAttribute", 42);
PA.setValue(myObject, "myAttribute", 42).setValue("myOtherAttribute", newValue");
PA.instantiate(MyClass.class);
PA.instantiate(MyClass.class, "Hello", "World", 42);
PA.invokeMethod(myObject, "addInt(int)", 42);
PA.invokeMethod(myObject, "addInteger(java.lang.Integer)", 42);
PA.invokeMethod(myObject, "addIntegers(java.lang.Integer...)", 42, 43, 44);
PA.invokeMethod(myObject, "addIntegerArray(java.lang.Integer[])", new Integer[] {42, 43, 44});</code>

You can access methods with all sorts of arguments (primitives, objects, varargs, arrays), just be sure to qualify the arguments correctly.

Caveats

Compatibility

PrivilegedAccessor uses a lot of unit tests to check its functionality - if you find a bug or missing feature, please feel free to contact us.

Advise

Do not use PrivilegedAccessor in production code - since it undermines the information hiding principle. Use it ONLY for testing or test setup/teardown purposes - e.g. for assigning mock objects, or asserting post-conditions.