2012-06-01 55 views
6

我有一個類,其中使用Runtime.getRuntime()從命令行執行腳本並獲取進一步處理的結果。如何在編寫JUnit時使用Runtime.getRuntime()?

但是,當我爲這個類編寫JUnit時,我無法找到一種方法來模擬/避免此Runtime.getRuntime()。exec()。

我不能使用EasyMock或PowerMock或除Mockito以外的任何其他模擬API。

請給我一種方法來解決這個問題,因爲這影響了代碼覆蓋率。

回答

13

您必須重構。提取Runtime.getRuntime().exec()成一個單獨的類:

public class Shell { 

    public Process exec(String command) { 
    return Runtime.getRuntime().exec(command); 
    } 

} 

現在insted的調用getRuntime()的明確注入Shell類莫名其妙地類測試:通過將其傳遞到構造

public class Foo { 

    private final Shell shell; 

    public Foo(Shell shell) { 
    this.shell = shell; 
    } 

    //... 
    shell.exec(...) 

} 

在JUnit測試純粹注入嘲笑Shell類:

@Mock 
private Shell shellMock; 

new Foo(shellMock); 

旁註:是的,我是不是創建一個Shell接口與一個實現。你介意嗎? Mockito不是。獎金:您現在可以驗證是否正確的過程被稱爲:

verify(shellMock).exec("/usr/bin/gimp"); 
+0

嗨,感謝您的快速回復! – unni

+0

但是,還有其他一些可能嗎?在哪裏我不必更改構造函數?既不使用像'this.shell = shell'這樣的setter – unni

+0

@ user1147417:我沒有看到任何可能性,至少沒有PowerMock。 '靜態'是邪惡的! –

3

Tomasz Nurkiewicz提供了一個美好的答案。但有一個選擇。

您可以將Runtime.getRuntime()移動到您正在測試的類中自己的方法中;然後用Mockito間諜進行測試。在Mockito間諜中,你可以用創建模擬Runtime的版本覆蓋這個特定的方法,然後做任何你喜歡的事情。

但是,Tomasz的方法更簡潔,我推薦徹底。我只是想說,還有另一種方法可以做到,而不訴諸Powermock。

+0

哎呀,大衛,我沒有看到你的答案,然後再次發佈相同。非常感謝您提供一個美妙的解決方案。 – unni

0

我使用的子類化和壓倒一切的(如邁克爾·C·羽毛書‘與遺留代碼有效地工作’解釋)

假設我們有下面的代碼:

public class CannotChange{ 
    public CannotChange(){} 
    public void TryingToTest() throws IOException { 
     ... 
     Process proc = Runtime.getRuntime().exec("command"); 
     ... 
    } 
} 

提取運行代碼轉換成一個受保護的方法:

public void TryingToTest() throws IOException { 
     ... 
     Process proc = execute("command"); 
     ... 
    } 
    protected Process execute(string command){ 
     return Runtime.getRuntime().exec(command); 
    }  

然後在測試類創建擴展CannotChange類並覆蓋一類 執行

public class CannotChangeTest{ 

    private class CannotChangeForTesting extends CannotChange{ 
     public CannotChangeForTesting(){ super(); } 
     @Override 
     public Process execute(String command){ 
     return null; //or a mocked object 
     } 
    } 

    @Test 
    public void TestMethod(){ 
     CannotChange cannotChange = new ForTestCannotChange(); 
     cannotChange.TryingToTest(); 
    } 
} 
相關問題