Reputation: 2789
I'm trying to write some Spock tests with Groovy to test some Java code (specifically a servlet Filter). I have some private static
and private static final
variables that I would like to mock, but I can't determine if there is a way to do this. I know metaClass
is available for methods, is there anything similar for variables?
For instance, I have:
public class MyFilter implements Filter {
private static WebResource RESOURCE;
private static final String CACHE_KEY = "key-to-be-used-for-cache";
... actual methods, etc ...
}
I've tried using Mock(MyFilter)
, as well as using Java reflection to change the value (based on this question and answer Change private static final field using Java reflection).
I would like to do this without adding something like Mockito or other frameworks, if that's possible, just use plain Groovy and Spock.
Thanks for any ideas!
UPDATE 1
At least for private static
variables I did get the following to work:
Field field = MyFilter.class.getDeclaredField("CACHE_KEY")
field.setAccessible(true)
field.set(null, "new-key-value")
But I still haven't been able to get around the final
aspect.
UPDATE 2
Thanks to Xv. I can now set this with the following:
Field field = MyFilter.class.getDeclaredField("CACHE_KEY")
field.setAccessible(true)
Field modifiersField = Field.class.getDeclaredField("modifiers")
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, "new-key-value")
Upvotes: 11
Views: 15827
Reputation: 4718
Based on what I learned from https://stackoverflow.com/a/25031713/239408, this works for me in spock
import java.lang.reflect.Field
import java.lang.reflect.Modifier
...
def setup() {
Field field = BackendCredentials.getDeclaredField("logger")
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, Mock(Logger))
}
Looks like you are missing the unsetting of the Modifier.FINAL
flag.
Upvotes: 13
Reputation: 8054
Either you need to use PowerMock (or another similar solution), or refactor your code. Spock does not support mocking of private/static/final methods on its own. This limitation is also present in Mockito, so that must give you a hint on best-practices.
Upvotes: 0