Los miembros externos estáticos burlados son nulos al probar una clase interna estática con PowerMockito.
Tengo una clase que se ve así:
public class OuterClass {
protected static Server s;
<pre><code>public static class CrazyEvent implements Runnable {
@Override
public void run() {
s.getSystemInfo();
}
}
</code></pre>
<p>}
Tiene un miembro estático “s” de tipo Server, y una clase interna estática llamada CrazyEvent que extrae información del Server.
Estoy intentando probar este método run() en PowerMockito:
@RunWith(PowerMockRunner.class)
@PrepareForTest(OuterClass.class)
public class StaticInnerClassTest {
private static class ServerMock extends Server {</p>
<pre><code> protected ServerMock(ServerConfig sc) {
super(sc);
}
@Override
public void start() {
}
}
private static class ServerConfigMock extends ServerConfig {
}
@Mock
ServerMock s = new ServerMock(new ServerConfigMock());
@Mock
UserMan um;
@InjectMocks
OuterClass.CrazyEvent ce = new OuterClass.CrazyEvent();
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(s.getUserMan()).thenReturn(um);
}
@Test
public void testInnerClass() {
ce.run();
}
</code></pre>
<p>}
Recorramos el código:
Estoy extendiendo el objeto Server real con ServerMock para poder anular un método molesto que se llama en el constructor. Mi objeto Server simulado es “s”. Idealmente, me gustaría inyectar esta simulación en la clase interna estática anidada porque debe usarla.
El problema es que, cuando llamo a ce.run(), “s” es nulo y la simulación no se inyecta correctamente. Soy bastante nuevo en PowerMockito y he estado luchando para encontrar información en SO sobre este caso en particular.
Edit:
Hay un logger de slf4j privado y estático en la clase externa que es nulo cuando se llama desde el método run() en la clase interna. No sé cómo instanciarlo. Intenté extender la clase externa y hacer que el logger sea protegido e instanciarlo de esa manera, pero sin suerte.
No importa. Accidentalmente dejé una llamada a PowerMockito.mockStatic() que estaba rompiendo todo.
davy.ai
Solución
El problema al que se enfrenta el autor es que el objeto simulado
s
no se inyecta correctamente en la clase interna estática anidadaCrazyEvent
, lo que hace que sea nulo cuando se llama al métodorun()
. Para inyectar correctamente el objeto simulado, el autor puede utilizar la anotación@PrepareForTest
junto con el métodoPowerMockito.whenNew()
para simular la creación del objetoCrazyEvent
e inyectar el objeto simulados
.Aquí tienes una versión actualizada del código de prueba:
La anotación
@PrepareForTest
se utiliza para indicar a PowerMockito que prepare la clase externaOuterClass
, así como la clase interna estática anidadaCrazyEvent
para la prueba. Esto permite que el objeto simulados
se inyecte correctamente enCrazyEvent
.A continuación, se utiliza el método
PowerMockito.whenNew()
para simular la creación de un nuevo objetoCrazyEvent
y devolver un objeto simulados
cuando se llama as.getSystemInfo()
en el métodorun()
. Por último, se llama al métodorun()
del objetoCrazyEvent
simulado y se pueden añadir cualquier aserción o verificación necesaria.Con estos cambios, el autor debería poder probar correctamente el método
run()
de la clase interna estática anidadaCrazyEvent
.