2014-12-18 66 views
6

我想用Groovy編寫一些Spock測試來測試一些Java代碼(特別是一個servlet過濾器)。我想要模擬一些private staticprivate static final變量,但我無法確定是否有辦法做到這一點。我知道metaClass可用於方法,有什麼類似的變量?使用Spock來模擬Java中的私有靜態最終變量

舉例來說,我有:

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

感謝十五。我現在可以用以下設置:

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

我猜這取決於它是如何被測試的,但是IMO使用一個旨在做你想做的事情的框架是更好的方法,並且更廣泛地適用,例如http://java.dzone.com/文章/ mocking-static-methods-groovy和http://stackoverflow.com/a/15834010/438992等 –

+0

感謝您的評論@DaveNewton - 尤其是Peter Niederwieser指出,只有groovy定義的方法可以在Spock中被模擬。我的情況是特定於類字段/變量,但我會檢查其他框架是否能夠爲我做到這一點。謝謝。 – mnd

+2

我知道這不是你正在尋找的東西,但是前一段時間我玩弄了[Spock和PowerMock](https://github.com/kriegaex/Spock_PowerMock)來模擬靜態方法。我不記得它是否也適用於(最終)靜態成員,只是爲自己嘗試。但是我真正想說的是,如果你的代碼很難測試,你不應該升級你的測試或測試工具,而是重構代碼的可測試性。我想當你需要像你想要的技巧或工具來給你想要的東西時,這是一種**代碼味道**。 – kriegaex

回答

5

根據我從https://stackoverflow.com/a/25031713/239408瞭解到,這對我的作品在斯波克

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

要麼你需要使用PowerMock(或其他類似的解決方案),或重構你的代碼。 Spock不支持自己私有/靜態/最終方法的嘲諷。這種限制也存在於Mockito中,因此必須向您提供有關最佳做法的暗示。