使用Spock在Java中模拟私有静态最终变量

时间:2014-12-18 17:43:27

标签: java unit-testing groovy spock

我试图用Groovy编写一些Spock测试来测试一些Java代码(特别是一个servlet Filter)。我有一些我想要模拟的private staticprivate 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")

2 个答案:

答案 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中也存在此限制,因此必须提供最佳实践的提示。