ProcessBuilder 및 Process를 사용하는 Java 방법을 단위 테스트하려면 어떻게해야합니까?

StackOverflow https://stackoverflow.com/questions/207636

문제

ProcessBuilder로 프로세스를 시작하는 Java 메소드가 있으며 출력을 바이트 어레이로 파이프 한 다음 프로세스가 완료되면 바이트 어레이를 반환합니다.

의사 코드 :

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

이 방법을 테스트하는 가장 좋은 방법은 무엇입니까? 나는 엄청나게 굉장한 것도 ProcessBuilder (최종)를 조롱하는 방법을 찾지 못했습니다. jmockit, 그것은 나에게 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)

이견있는 사람?


대답 -OLAF가 권장했듯이 그 선을 인터페이스로 리팩토링했습니다.

Process start(String param) throws IOException;

이제이 인터페이스의 인스턴스를 일반적으로 원래 줄과 함께 기본 구현을 사용하여 (생성자에서) 테스트하고 싶은 클래스로 전달합니다. 테스트하고 싶을 때 간단히 인터페이스의 모의 구현을 사용합니다. 내가 여기서 과도하게 침입하는지 궁금하지만, 매력처럼 작동합니다 ...

도움이 되었습니까?

해결책

조롱 할 수업에서 자신을 보호하십시오. 실제로 원하는 작업 (예 : 외부 프로세스가 전혀 관련되어 있다는 사실을 숨기는) 또는 프로세스 및 프로세스 빌더에 대해서만 인터페이스를 만듭니다.

당신은 그 프로세스 빌더 및 프로세스 작업을 테스트하고 싶지 않으며, 출력으로 만 작업 할 수 있다는 것만 테스트하고 싶지 않습니다. 인터페이스를 만들 때, 하나의 사소한 구현 (쉽게 검사 할 수있는) 대의원 대의원을 프로세스 빌더 및 프로세스로 만들 때 다른 구현은이 동작을 조롱합니다. 나중에 다른 프로세스를 시작하지 않고 필요한 일을하는 다른 구현도있을 수도 있습니다.

다른 팁

최신 JMockit (0.98+) 릴리스를 사용하면 프로세스 및 프로세스 빌더와 같은 JRE 클래스를 쉽게 조롱 할 수 있어야합니다. 따라서 테스트를 위해 인터페이스를 만들 필요가 없습니다 ...

전체 예제 (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);
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top