2010-07-13 12 views
33

Ich möchte den Wert eines privaten Felds mithilfe der Reflektion für Komponententests festlegen.Wert des privaten statischen Felds festlegen

Problem ist, dass das Feld statisch ist.

Hier ist, was aus ich arbeite:

/** 
    * 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; 
    } 

ich dies zu realisieren wird wahrscheinlich bereits auf SO beantwortet worden, aber meine Suche es nicht wieder auftauchen ...

+3

Die offensichtliche Antwort ist "Jasus, mutieren nicht Statik oder Privates anderer Klassen." Sie könnten die Parametrierung von oben versuchen. –

+0

Wenn Sie Feder verwenden, können Sie @Autowired auf einem privaten Feld festlegen. Wenn Sie diese Instanz durch ein Pseudonym ersetzen müssen, müssen Sie das mithilfe der Reflektion von der Testmethode ändern –

Antwort

38

Grundsätzlich ist das Problem Ihre Hilfsmethode, die davon ausgeht, dass Sie eine Instanz haben. Es ist relativ einfach, ein privates statisches Feld festzulegen - es ist genau dasselbe wie für ein Instanzfeld, außer dass Sie null als Instanz angeben. Leider verwendet Ihre Hilfsmethode die Instanz, um die Klasse zu erhalten, und verlangt, dass sie nicht null ist ...

Ich würde Toms Vorbehalt wiederholen: Tu das nicht. Wenn dies eine Klasse ist, dass Sie unter Ihrer Kontrolle haben, ich ein Paket Level-Methode erstellen würde:

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

Allerdings ist hier eine komplette Probe, wenn Sie wirklich , wirklich setzen wollen es mit Reflexion:

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

Ich glaube, Unit-Tests sollten uns nicht dazu bringen alles in Produktionsklassen, wie du es sagst: Ich würde eine Methode auf Paketebene erstellen –

5

Übergeben Sie einfach null für das Objektinstanzargument. Also:

field.set(null, p_fieldValue); 

Damit können Sie das statische Feld festlegen.

Verwandte Themen