![](/img/trans.png)
[英]How to Mock LdapTemplate in Java and get full code coverage
[英]How to mock Final classes and have code coverage
我無法找到解決JUnit問題的解決方案,因此我嘗試將其簡化為最大程度,因此希望它易於理解。
基本上,我正在嘗試測試此類:
public class PB {
public int startProcessBuilder() {
int status = 1;
try {
ProcessBuilder pb = new ProcessBuilder("java", "-jar", ".....");
pb.directory(new File("/directory"));
Process process = pb.start();
status = process.waitFor();
} catch (IOException | InterruptedException e) {
System.out.println(e.getMessage());
}
return status;
}
}
所以我想出了這個測試:
@RunWith(PowerMockRunner.class)
@PrepareForTest({ ProcessBuilder.class, PB.class })
public class PBTest {
private PB spyInstance = Mockito.spy(PB.class);
private ProcessBuilder processBuilderMock = PowerMockito.mock(ProcessBuilder.class);
private Process processMock = Mockito.mock(Process.class);
@Before
public void initialize() throws Exception {
PowerMockito.whenNew(ProcessBuilder.class).withParameterTypes(String[].class).withArguments(anyVararg())
.thenReturn(processBuilderMock);
PowerMockito.doReturn(processMock).when(processBuilderMock).start();
}
@Test
public void testStartProcessBuilder() throws Exception {
assertThat(spyInstance.startProcessBuilder(), is(0));
}
}
我知道我的測試運行成功,但是在我所工作的公司中,我們正在使用jacoco和eclemma來顯示代碼覆蓋率,並且這是一個已知問題,如果我們正在測試的類,則所有代碼都顯示為0%覆蓋率在@PrepareForTest批注中。
因此,有一段時間,我們正在使用MockitoJUnitRunner( http://www.notonlyanecmplace.com/make-eclemma-test-coverage-work-with-powermock/ )解決一個已知的解決方案。
@RunWith(MockitoJUnitRunner.class)
@PrepareForTest({ ProcessBuilder.class, PB.class })
public class PBTest {
private PB spyInstance = Mockito.spy(PB.class);
private ProcessBuilder processBuilderMock = PowerMockito.mock(ProcessBuilder.class);
private Process processMock = Mockito.mock(Process.class);
@Rule
public PowerMockRule rule = new PowerMockRule();
static {
PowerMockAgent.initializeIfNeeded();
}
@Before
public void initialize() throws Exception {
PowerMockito.whenNew(ProcessBuilder.class).withParameterTypes(String[].class).withArguments(anyVararg())
.thenReturn(processBuilderMock);
PowerMockito.doReturn(processMock).when(processBuilderMock).start();
}
@Test
public void testStartProcessBuilder() throws Exception {
assertThat(spyInstance.startProcessBuilder(), is(0));
}
}
現在出現了真正的問題:當我嘗試運行測試時,出現此異常:org.mockito.exceptions.misusing.NotAMockException:傳遞給when()的參數不是模擬的! 並顯示以下行:
PowerMockito.doReturn(processMock).when(processBuilderMock).start();
是的,很明顯,processBuilderMock不是模擬而是Powermock,所以我嘗試替換了這兩行
private ProcessBuilder processBuilderMock = PowerMockito.mock(ProcessBuilder.class);
PowerMockito.doReturn(processMock).when(processBuilderMock).start();
這樣 :
private ProcessBuilder processBuilderMock = Mockito.mock(ProcessBuilder.class);
PowerMockito.doReturn(processMock).when(processBuilderMock).start();
但是,然后當然: Cannot mock/spy class java.lang.ProcessBuilder... because it is a final class
(可能是為什么我最初使用PowerMock的原因)
我有什么選擇?
您可以將PB
類設計為易於測試。 一種方法是提取ProcessBuilder
參數:
public class PB {
public int startProcessBuilder(String... args) {
try {
ProcessBuilder pb = new ProcessBuilder(args);
在測試的后面,您可以使用一個小的“ Hello World”測試JAR:
new PB().startProcessBuilder("java", "-jar", "path-to-test-jar");
或使用標准的echo
命令,無論使用什么操作系統,該命令都應具有相同的語法:
new PB().startProcessBuilder("echo", "Hello", "World");
您不需要模擬任何東西,而實際上使用模擬JAR調用模擬Java進程。
您要增加覆蓋面會遇到很多麻煩,這一事實表明您當前的開發過程值得懷疑。 覆蓋范圍本身並不是目標,它是使您對代碼充滿信心的度量標准。 如果您必須避免使用@PrepareForTest
來增強效果,那有什么意義呢?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.