我试图用Groovy编写一些Spock测试来测试一些Java代码(特别是一个servlet Filter)。我有一些我想要模拟的private static
和private static final
变量,但我无法确定是否有办法执行此操作。我知道metaClass
可用于方法,变量有什么类似的东西吗?
例如,我有:
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反射来更改值(基于此问题并回答Change private static final field using Java reflection)。
我想这样做而不添加像Mockito或其他框架这样的东西,如果可能的话,只需使用普通的Groovy和Spock。
感谢您的任何想法!
更新1
至少对于private static
变量,我确实得到以下工作:
Field field = MyFilter.class.getDeclaredField("CACHE_KEY")
field.setAccessible(true)
field.set(null, "new-key-value")
但我仍然无法绕过final
方面。
更新2
感谢Xv。我现在可以用以下内容进行设置:
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")
答案 0 :(得分:8)
根据我从https://stackoverflow.com/a/25031713/239408学到的东西,这对我来说是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
标志的取消设置。
答案 1 :(得分:1)
您需要使用PowerMock(或其他类似解决方案),或重构您的代码。 Spock不支持自己模拟私有/静态/最终方法。 Mockito中也存在此限制,因此必须提供最佳实践的提示。