2010-07-13 25 views
33

Quiero establecer el valor de un campo privado utilizando la reflexión para probar la unidad.Establecer el valor del campo estático privado

El problema es que ese campo es estático.

Aquí es lo que estoy trabajando desde:

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

Soy consciente de que probablemente ya ha sido contestada en el SO, pero mi búsqueda no hasta convertirlo ...

+3

La respuesta obvia es "Jasus, no mutes statics ni partes privadas de otras clases". Puede intentar la parametrización desde arriba. –

+0

si está utilizando la primavera, puede configurar @Autowired en un campo privado; luego, si necesita reemplazar esa instancia con un simulacro, debe cambiar eso utilizando la reflexión del método de prueba –

Respuesta

38

Básicamente el problema es su método de utilidad, que asume que tiene una instancia. Es razonablemente fácil establecer un campo estático privado; es exactamente el mismo procedimiento que para un campo de instancia, excepto que especifique null como instancia. Lamentablemente, su método de utilidad utiliza la instancia para obtener la clase, y requiere que sea no nula ...

Me gustaría hacer eco de la advertencia de Tom: no hagas eso. Si se trata de una clase que tiene bajo su control, que crearía un método nivel de paquete:

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

Sin embargo, he aquí una muestra completa si muy, muy desea establecer con la reflexión:

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

. Creo que las pruebas unitarias no nos obligan a hacer cualquier cosa en las clases de producción como lo indique: crearía un método de nivel de paquete –

5

Solo pase null para el argumento objeto-instancia. Entonces:

field.set(null, p_fieldValue); 

Esto le permitirá establecer el campo estático.

Cuestiones relacionadas