使用 Spock 在 Java 中模拟私有静态最终变量 [英] Using Spock to mock private static final variables in Java
问题描述
我正在尝试使用 Groovy 编写一些 Spock 测试来测试一些 Java 代码(特别是 servlet 过滤器).我有一些想要模拟的 private static
和 private static final
变量,但我无法确定是否有办法做到这一点.我知道 metaClass
可用于方法,变量是否有类似的东西?
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?
例如,我有:
public class MyFilter implements Filter {
private static WebResource RESOURCE;
private static final String CACHE_KEY = "key-to-be-used-for-cache";
... actual methods, etc ...
}
我尝试过使用 Mock(MyFilter)
,以及使用 Java 反射来更改值(基于此问题和答案 使用 Java 反射更改私有静态最终字段).
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).
我想在不添加类似 Mockito 或其他框架的情况下执行此操作,如果可能,只需使用普通的 Groovy 和 Spock.
I would like to do this without adding something like Mockito or other frameworks, if that's possible, just use plain Groovy and Spock.
感谢您的任何想法!
更新 1
至少对于 private static
变量,我确实得到了以下工作:
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")
但我仍然无法绕过final
方面.
But I still haven't been able to get around the final
aspect.
更新 2
感谢 Xv.我现在可以使用以下内容进行设置:
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")
推荐答案
基于我从 https://stackoverflow.com 学到的/a/25031713/239408,这在 spock 中对我有用
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))
}
看起来您缺少取消设置 Modifier.FINAL
标志.
Looks like you are missing the unsetting of the Modifier.FINAL
flag.
这篇关于使用 Spock 在 Java 中模拟私有静态最终变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!