Simulacros De Ejecución.getRuntime()?
-
20-09-2019 - |
Pregunta
Cualquiera puede hacer cualquier sugerencia sobre cómo utilizar mejor EasyMock a esperar una llamada a Runtime.getRuntime().exec(xxx)
?
Me podía mover la llamada a un método de otra clase que implementa una interfaz, pero no más bien en un mundo ideal.
interface RuntimeWrapper {
ProcessWrapper execute(String command) throws IOException;
}
interface ProcessWrapper {
int waitFor() throws InterruptedException;
}
Me preguntaba si alguien tenía alguna otra sugerencia?
Solución
Su clase no debe llamar Runtime.getRuntime()
. se debe esperar una Runtime
a establecer como su dependencia, y trabajar con él. Luego, en la prueba se puede proporcionar fácilmente una maqueta y configurarlo como una dependencia.
Como comentario, sugeriría viendo esta conferencia sobre OO Diseño de la capacidad de prueba .
Actualización: no vi el constructor privado. Usted puede intentar usar href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/instrument/package-summary.html" Java bytecode instrumentación con el fin de añadir otro constructor o hacer que el público constructor, pero que podría llegar a ser imposible, así (si hay algunas restricciones en la clase).
Por lo que su opción es hacer una envoltura (como se sugiere en la pregunta), y seguir el enfoque de la dependencia de la inyección.
Otros consejos
Bozho arriba está la OMI Solución Correcta.Pero no es la única solución.Usted podría utilizar PowerMock o JMockIt.
El Uso De PowerMock:
package playtest;
public class UsesRuntime {
public void run() throws Exception {
Runtime rt = Runtime.getRuntime();
rt.exec("notepad");
}
}
package playtest;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.legacy.PowerMockRunner;
import static org.powermock.api.easymock.PowerMock.*;
import static org.easymock.EasyMock.expect;
@RunWith(PowerMockRunner.class)
@PrepareForTest( { UsesRuntime.class })
public class TestUsesRuntime {
@Test
public void test() throws Exception {
mockStatic(Runtime.class);
Runtime mockedRuntime = createMock(Runtime.class);
expect(Runtime.getRuntime()).andReturn(mockedRuntime);
expect(mockedRuntime.exec("notepad")).andReturn(null);
replay(Runtime.class, mockedRuntime);
UsesRuntime sut = new UsesRuntime();
sut.run();
}
}
Tal vez en lugar de burlarse Runtime.getRuntime().exec()
que podría "simulacro" el script / programa / etc. se supone que debe estar llamando.
En lugar de pasar la cadena de línea de comandos reales en exec()
, escribir un script de prueba y ejecutarlo en su lugar. Usted podría tener la secuencia de comandos devuelve valores no modificables que podría poner a prueba contra al igual que una clase burlado.
Esta es la manera que lo haría con EasyMock 3.0 (y JUnit 4):
import org.junit.*;
import org.easymock.*;
import static org.easymock.EasyMock.*;
public final class EasyMockTest extends EasyMockSupport
{
@Test
public void mockRuntimeExec() throws Exception
{
Runtime r = createNiceMock(Runtime.class);
expect(r.exec("command")).andReturn(null);
replayAll();
// In tested code:
r.exec("command");
verifyAll();
}
}
El único problema con la prueba anterior es que el objeto Runtime
necesita ser pasado a codificar bajo prueba, que le impide el uso de Runtime.getRuntime()
.
Con JMockit , por el contrario, el siguiente ensayo se puede escribir, evitando de ese problema:
import org.junit.*;
import mockit.*;
public final class JMockitTest
{
@Test
public void mockRuntimeExec() throws Exception
{
final Runtime r = Runtime.getRuntime();
new NonStrictExpectations(r) {{ r.exec("command"); times = 1; }};
// In tested code:
Runtime.getRuntime().exec("command");
}
}