2011-03-21 18 views
34

Tengo dificultades para encontrar una manera de establecer un campo estático de una clase. Básicamente es así:Prueba de PowerMock: establecer el campo estático de la clase

public class Foo{ 
    // ... 
    private static B b = null; 
} 

donde B es otra clase.

¿Hay alguna manera de hacer esto en PowerMock que no sea con setInternalStateFromContext()? Usar el método de clase de contexto parece un poco exagerado para establecer un campo.

Gracias.

Respuesta

4

sólo tiene que hacer:

Whitebox.setInternalState(Foo.class, b); 

donde b es la instancia de B que desea establecer.

+0

¿El valor que desea establecer para 'b' es simplemente otro parámetro de setInternalState()? –

+0

Sí, es el segundo parámetro. P.ej. B nuevo = B(); Whitebox.setInternalState (Foo.class, b); – Johan

+2

esto funciona siempre que establezca un valor no nulo. Y si hay un solo campo con la clase de b. – cproinger

73
Whitebox.setInternalState(Foo.class, b); 

funciona siempre y cuando se establece un valor no nulo, y si hay solamente un campo con la clase de B. Si no puede confiar en ese lujo, debe proporcionar el nombre del campo y enviar el null al tipo que desea establecer. En ese caso, tendría que escribir algo como esto:

Whitebox.setInternalState(Foo.class, "b", (B)null); 
+7

¿Por qué no se ha aceptado esta respuesta? –

+0

@Matt: Porque OP no está registrado y "Visto por última vez 13 de abril a las 16:37". – glenneroo

0

Puede utilizar getAllStaticFields y tratar de ponerlos

Ejemplo:

YourFieldClass newValue; 
final Set<Field> fields = Whitebox.getAllStaticFields(YourClass.class); 
     for (final Field field : fields) { 
      if (YourFieldClass.class.equals(field.getType())) { // or check by field name 
       field.setAccessible(true); 
       field.set(YourClass.class, newValue); 
      }  } 
+0

¿No se supone que es 'field.set (YourFieldClass.class, newValue);' ?? – Arun

+0

No. Puede verificar api: [link] (http://docs.oracle.com/javase/6/docs/api/java/lang/reflect/Field.html#set (java.lang.Object, java.lang.Object)) donde dice _obj - el objeto cuyo campo debe modificarse_ –

13

Prueba esto:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({Foo.class}) 
public class FooTest { 

    @Test 
    public void shouldMockPrivateStaticField() throws IllegalAccessException { 
     // given 
     Foo foo = new Foo(); 
     Field field = PowerMockito.field(Foo.class, "b"); 
     field.set(Foo.class, mock(B.class)); 

No funciona para primitivas y primitivas envolturas.

0

aquí voy a establecer el valor para "android.os.Build.VERSION.RELEASE", donde VERSION es el nombre de la clase y RELEASE es el valor final de la cadena estática.

Si el campo subyacente es definitiva, el método tiros un IllegalAccessException menos setAccessible (verdadero) ha tenido éxito para este campo y este campo es no estático, NoSuchFieldException necesidades que se añade cuando utiliza field.set() método

@RunWith(PowerMockRunner.class) 
@PrepareForTest({Build.VERSION.class}) 
public class RuntimePermissionUtilsTest { 
@Test 
public void hasStoragePermissions() throws IllegalAccessException, NoSuchFieldException { 
    Field field = Build.VERSION.class.getField("RELEASE"); 
    field.setAccessible(true); 
    field.set(null,"Marshmallow"); 
} 
} 

sin w el valor de String RELEASE devolverá "Marshmallow".

Cuestiones relacionadas