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?

¿Fue útil?

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");
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top