2010-07-13 109 views
33

我想使用反射設置專用字段的值以進行單元測試。私有靜態字段的設置值

問題是,該字段是靜態的。

這裏就是我從工作:

/** 
    * Use to set the value of a field you don't have access to, using reflection, for unit testing. 
    * 
    * Returns true/false for success/failure. 
    * 
    * @param p_instance an object to set a private field on 
    * @param p_fieldName the name of the field to set 
    * @param p_fieldValue the value to set the field to 
    * @return true/false for success/failure 
    */ 
    public static boolean setPrivateField(final Object p_instance, final String p_fieldName, final Object p_fieldValue) { 
    if (null == p_instance) 
     throw new NullPointerException("p_instance can't be null!"); 
    if (null == p_fieldName) 
     throw new NullPointerException("p_fieldName can't be null!"); 

    boolean result = true; 

    Class<?> klass = p_instance.getClass(); 

    Field field = null; 
    try { 
     field = klass.getDeclaredField(p_fieldName); 

     field.setAccessible(true); 
     field.set(p_instance, p_fieldValue); 

    } catch (SecurityException e) { 
     result = false; 
    } catch (NoSuchFieldException e) { 
     result = false; 
    } catch (IllegalArgumentException e) { 
     result = false; 
    } catch (IllegalAccessException e) { 
     result = false; 
    } 

    return result; 
    } 

我意識到這有可能已經被回答了SO,但我的搜索並沒有把它上升...

+3

顯而易見的答案是「Jasus,不要改變其他類別的靜態或私有化。」你可以嘗試從上面的參數化。 – 2010-07-13 16:09:33

+0

如果你使用的是spring,你可以在私有域中設置@Autowired,那麼如果你需要用模擬替換那個實例,你需要使用測試方法中的反射來改變它 – 2011-07-04 18:19:27

回答

38

基本問題你的實用方法,它假定你有一個實例。設置私有靜態字段相當容易 - 除了指定null作爲實例外,它與實例字段的過程完全相同。不幸的是,你的實用方法使用實例來獲得類,並要求它是非空的...

我會迴應湯姆的警告:不要這樣做。如果這是你有你的控制下的班,我想創建一個包級別的方法:

void setFooForTesting(Bar newValue) 
{ 
    foo = newValue; 
} 

但是,這裏有一個完整的樣本,如果你真的,真的想與反射設置:

import java.lang.reflect.*; 

class FieldContainer 
{ 
    private static String woot; 

    public static void showWoot() 
    { 
     System.out.println(woot); 
    } 
} 

public class Test 
{ 
    // Declared to throw Exception just for the sake of brevity here 
    public static void main(String[] args) throws Exception 
    { 
     Field field = FieldContainer.class.getDeclaredField("woot"); 
     field.setAccessible(true); 
     field.set(null, "New value"); 
     FieldContainer.showWoot(); 
    } 
} 
+8

我認爲單元測試不應該促使我們做生產類中的任何東西,如你所說的:我會創建一個包級別的方法 – 2011-07-04 17:42:42

5

只需傳遞null作爲對象實例參數。所以:

field.set(null, p_fieldValue); 

這會讓你設置靜態字段。