What do I use instead of Whitebox in Mockito 2.2 to set fields?
You can use FieldSetter in Mockito2.x
import org.mockito.internal.util.reflection.FieldSetter;
FieldSetter.setField(eventHandler,eventHandler.getClass().getDeclaredField("securityService"), securityService);
The cleanest, neatest and most portable way without reinventing the wheel is to use Apache Commons' FieldUtils
.
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/reflect/FieldUtils.html
The answer to your question would then be
public static void setStaticFieldValue(
@NonNull final Class<?> clz,
@NonNull final String fieldName,
@NonNull final Object value) throws Exception {
final Field f = FieldUtils.getField(clz, fieldName, true);
FieldUtils.removeFinalModifier(f);
f.set(null, value);
}
Note that Whitebox
was always in the org.mockito.internal
package. Beyond the incrementing of the major version number, the internal
designation is a giveaway that the package may be subject to breaking changes.
If you do want to make it a point to set otherwise-inaccessible fields in your test, you can do so in the same way that setInternalState
does, which is just to identify the field in the hierarchy, call setAccessible
on it, and then set it. The full code is here on grepcode. You can also examine a number of other ways to set inaccessible state in tests.
public static void setInternalState(Object target, String field, Object value) {
Class<?> c = target.getClass();
try {
Field f = getFieldFromHierarchy(c, field); // Checks superclasses.
f.setAccessible(true);
f.set(target, value);
} catch (Exception e) {
throw new RuntimeException(
"Unable to set internal state on a private field. [...]", e);
}
}
However, in situations like this, my general advice is to stop fighting the tools: Java's four levels of encapsulation (public, protected, package, private) are not necessarily granular enough to express the degree of protection you're trying to express, and it's often much easier to add a well-documented initialization method or constructor override to override the dependencies as you're trying to do reflectively. If you put your tests in the same Java package as the class it tests, you can often even make the fields or method/constructor package-private, which is also a good reason to set up parallel source folders src
and tests
(etc) that represent two halves of the same Java package.
Though some treat this additional method or constructor as "API pollution", I see it instead as coding to the requirements of one of your class's most important consumers—its own test. If you need a pristine external interface, you can easily define one separately such that you can hide any details you'd like. However, you may find you like the ability to inject any real or mock implementation directly into your now-more-flexible component, at which point you may want to look into dependency injection patterns or frameworks.
If you are using Spring (the spring-test library specifically), you can simply use ReflectionTestUtils.setField
instead of Whitebox.setInternalState