ProcessBuilder 및 Process를 사용하는 Java 방법을 단위 테스트하려면 어떻게해야합니까?
-
03-07-2019 - |
문제
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);
}
}