Pergunta

I tem um método Java que inicia-se um processo com ProcessBuilder, e tubos da sua saída para uma matriz de bytes, e, em seguida, retorna sua matriz de bytes quando o processo está acabado.

Pseudo-código:

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

Qual seria a melhor maneira de ir sobre a unidade testar este método? Eu não encontrei uma maneira de zombar ProcessBuilder (é final), mesmo com a incrivelmente impressionante JMockit , dá-me um 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)

Qualquer pensamento?


Resposta - Como Olaf recomendado, acabei refatoração essas linhas a uma interface

Process start(String param) throws IOException;

Agora eu passar uma instância desta interface para a classe Eu queria teste (em seu construtor), normalmente usando uma implementação padrão com as linhas originais. Quando eu quiser testar eu simplesmente usar uma implementação simulada da interface. Funciona como um encanto, embora eu me pergunto se eu estou over-interface aqui ...

Foi útil?

Solução

Proteja-se das classes de ser ridicularizado. Criar uma interface tanto para fazer o que você realmente quer (por exemplo, escondendo o fato de que processos externos estão envolvidos em tudo) ou apenas para Processo e ProcessBuilder.

Você não quer teste, que ProcessBuilder e trabalho processo, só que você pode trabalhar com a sua saída. Quando você cria uma interface de uma implementação trivial (que pode ser facilmente inspecionado) delegados para ProcessBuilder e Processo, outra implementação simulações esse comportamento. Mais tarde, você pode até ter uma outra aplicação que faz o que você precisa sem iniciar outro processo.

Outras dicas

Com versões mais recentes do JMockit (0.98+), você deve ser capaz de aulas JRE facilmente simulados como Processos e ProcessBuilder. Assim, não há necessidade de criar interfaces de apenas para o teste ...

exemplo completa (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);
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top