How can I mock a final static variable using PowerMock

15,955 views
Skip to first unread message

Timothy

unread,
May 31, 2012, 1:58:27 AM5/31/12
to PowerMock
Is it possible to use Powermock to replace a final static variable in
a class? I have a Util class that makes use of a another (service)
class to retrieve a value from our CMS. During my unit tests I want to
mock the service and only test the doSomething() method in my class.

public class SomeUtilClass {
private static final ServiceClass service = new ServiceClass();

public static String doSomething(...) {
...
}
}

I know it is possible using reflection, but I was just wondering if it
is possible using PowerMock.

Johan Haleby

unread,
May 31, 2012, 2:16:40 AM5/31/12
to powe...@googlegroups.com
Hi, 

I don't think this is possible since static final variables are _compiled_ into constants and the reference to the constant will be inlined in your code. But I'm not really sure this is always the case.. I may not remember it correctly but I _think_ I was able to replace some static final fields using sun.misc.Unsafe in the PowerMock DeepCloner Objenesis project. This approach is NOT recommended though. You could try experimenting with "stub(field(..)).." or "replace(field(..))" in PowerMock (see org.powermock.api.support.membermodification.MemberModifier) or you could try suppressing the static initializer of the class using the @SuppressStaticInitializationFor annotation and then setting the field using reflection. But I'm not sure any of this will actually work for static final fields. Let us know :)

Regards,
/Johan


--
You received this message because you are subscribed to the Google Groups "PowerMock" group.
To post to this group, send email to powe...@googlegroups.com.
To unsubscribe from this group, send email to powermock+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/powermock?hl=en.


Timothy

unread,
Jun 1, 2012, 5:32:37 AM6/1/12
to powe...@googlegroups.com
Hi,
 
Thanks for your suggestions!
 
What I finally did is using reflection to remove the final modifier. In my setup() method I just replace the var with the mock and in my teardown I replace the mock again with the real implementation.
 
Util method:
private static void setFinalStatic(Field field, Object newValue) throws Exception {
   Field field = ClassWhereToMockStaticFinalVar.class.getDeclaredField("FieldName");   
   field.setAccessible(true);
 
   // remove final modifier from field
   Field modifiersField = Field.class.getDeclaredField("modifiers");
   modifiersField.setAccessible(true);
   modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
   field.set(null, newValue);
}
 
Regards,
Timo

Op donderdag 31 mei 2012 08:16:40 UTC+2 schreef Johan Haleby het volgende:
Hi, 

I don't think this is possible since static final variables are _compiled_ into constants and the reference to the constant will be inlined in your code. But I'm not really sure this is always the case.. I may not remember it correctly but I _think_ I was able to replace some static final fields using sun.misc.Unsafe in the PowerMock DeepCloner Objenesis project. This approach is NOT recommended though. You could try experimenting with "stub(field(..)).." or "replace(field(..))" in PowerMock (see org.powermock.api.support.membermodification.MemberModifier) or you could try suppressing the static initializer of the class using the @SuppressStaticInitializationFor annotation and then setting the field using reflection. But I'm not sure any of this will actually work for static final fields. Let us know :)

Regards,
/Johan
Reply all
Reply to author
Forward
0 new messages