unitaria tutorial referencia recibir prueba parametros metodos español ejemplos con java unit-testing mocking jmockit

java - tutorial - prueba unitaria con junit



¿Cómo pruebo la unidad de un método Java que utiliza ProcessBuilder y Process? (2)

Tengo un método Java que inicia un Proceso con ProcessBuilder, y canaliza su salida en una matriz de bytes, y luego devuelve su matriz de bytes cuando el proceso finaliza.

Pseudo-código:

ProcessBuilder b = new ProcessBuilder("my.exe") Process p = b.start(); ... // get output from process, close process

¿Cuál sería la mejor manera de realizar pruebas unitarias de este método? No he encontrado una manera de burlarme de ProcessBuilder (es definitivo), incluso con el JMockit increíblemente increíble, me da un NoClassDefFoundError:

java.lang.NoClassDefFoundError: test/MockProcessBuilder at java.lang.ProcessBuilder.<init>(ProcessBuilder.java) at mypackage.MyProcess.start(ReportReaderWrapperImpl.java:97) at test.MyProcessTest.testStart(ReportReaderWrapperImplTest.java:28)

¿Alguna idea?

Respuesta - Como Olaf me recomendó, terminé refactorizando esas líneas a una interfaz

Process start(String param) throws IOException;

Paso ahora una instancia de esta interfaz a la clase que quería probar (en su constructor), normalmente usando una implementación predeterminada con las líneas originales. Cuando quiero probar simplemente utilizo una implementación simulada de la interfaz. Funciona como un amuleto, aunque me pregunto si estoy haciendo demasiadas interfaces aquí ...


Protégete de las clases para burlarte. Cree una interfaz para hacer lo que realmente quiere (por ejemplo, ocultar el hecho de que los procesos externos están involucrados) o solo para Process y ProcessBuilder.

No desea probar, que ProcessBuilder y Process funcionan, solo que puede trabajar con sus resultados. Cuando se crea una interfaz, una implementación trivial (que se puede inspeccionar fácilmente) delega a ProcessBuilder y Process, otra implementación se burla de este comportamiento. Más adelante, incluso podría tener otra implementación que haga lo que necesita sin iniciar otro proceso.


Con las versiones más recientes de JMockit (0.98+) debería poder simular fácilmente las clases de JRE como Process y ProcessBuilder. Entonces, no es necesario crear interfaces solo para probar ...

Ejemplo completo (usando JMockit 1.16):

public class MyProcessTest { public static class MyProcess { public byte[] run() throws IOException, InterruptedException { Process process = new ProcessBuilder("my.exe").start(); process.waitFor(); // Simplified example solution: InputStream processOutput = process.getInputStream(); byte[] output = new byte[8192]; int bytesRead = processOutput.read(output); return Arrays.copyOf(output, bytesRead); } } @Test public void runProcessReadingItsOutput(@Mocked final ProcessBuilder pb) throws Exception { byte[] expectedOutput = "mocked output".getBytes(); final InputStream output = new ByteArrayInputStream(expectedOutput); new Expectations() {{ pb.start().getInputStream(); result = output; }}; byte[] processOutput = new MyProcess().run(); assertArrayEquals(expectedOutput, processOutput); } }