2012-09-02 58 views
3

我發現真的很難爲此方法編寫單元測試,它基本上在用戶鍵入退出命令時退出程序。Java編寫單元測試用於在控制檯中退出用戶類型時退出程序

SytemExit類:

public class SystemExit { 
    public void exit(int status) { 
     System.exit(status); 
    } 
} 

我的靜態方法:

public static void exitWhenQuitDetected() { 
final SystemExit systemExit = new SystemExit(); 
final String QUIT = "quit"; 
String line = ""; 
try { 
    final InputStreamReader input = new InputStreamReader(System.in); 
    final BufferedReader in = new BufferedReader(input); 
    while (!(line.equals(QUIT))) { 
     line = in.readLine(); 
     if (line.equals(QUIT)) { 
      System.out.println("You are now quiting the program");     
      systemExit.exit(1); 
     } 
    } 
} catch (Exception e) { 
    System.err.println("Error: " + e.getMessage()); 
} 
} 

東西是不完全正確這裏,因爲我很努力的單元測試方法exitWhenQuitDetected(我用的Mockito的嘲諷)。如何嘲笑InputStreamReader並驗證SystemExit.exit方法在看到退出時被調用?你可以在這個燈上點亮一些燈嗎?謝謝。

添加了我目前正在進行的測試,它不起作用。

@Test 
@Ignore 
public void shouldExitProgramWhenTypeQuit() { 
    String quit = "quit";   
    SystemExit systemExit = mock(SystemExit.class); 
    try { 
     BufferedReader bufferedReader = mock(BufferedReader.class); 
     when(bufferedReader.readLine()).thenReturn(quit + "\n"); 
     SomeClass.exitWhenQuitDetected(); 
     verify(systemExit, times(1)).exit(1); 
    } catch (IOException e) {   
     e.printStackTrace(); 
    }  
} 
+0

請添加您的Mockito代碼。 – 2012-09-02 08:45:24

+0

這正是我所要求的,我正在努力想出這個測試。 –

+0

歡迎來到Stack Overflow!我們鼓勵你[研究你的問題](http://stackoverflow.com/questions/how-to-ask)。如果你已經[嘗試了某些東西](http://whathaveyoutried.com/),請將其添加到問題中 - 如果沒有,請先研究並嘗試您的問題,然後再回來。 – 2012-09-02 08:49:19

回答

1

您已經完成了90%的工作,將實際的退出代碼放在一個單獨的類中,沒有自己的邏輯。您的困難是由您使用靜態方法引起的。

我會建議使exitWhenQuitDetected不是靜態的。把它放在一個你可以在需要時實例化的類中,並且你可以用嘲弄的SystemExit來創建。像這樣的東西。

然後,在您的測試,你可以做的SystemExit一個模擬,並使用SomeClass的包私有構造函數來創建一個對象,將使用您的模擬爲exiter。然後你可以運行你的測試,並在你的模擬SystemExitverify

+0

需要最小變化的實用答案+1。我仍然喜歡我的答案(沒有代碼更改),但後來我有點偏見:) – Brad

1

還有就是要考驗你,因爲鍛鍊會導致JVM退出SystemExit類沒有真正的方法。您可能可以使用SecurityManager來檢測和拒絕System.exit(),但測試一行代碼將會花費大量工作量。

你做得對 - 你已經把功能拉到了一個小班。如果我是你,我會在它上面放一個接口,並通過接口將它注入解析代碼。然後在你的測試中,你可以注入一個模擬並測試你的解析代碼在模擬上用正確的退出代碼調用exit()方法。

SystemExit類中的代碼很小並且足夠獨立,足以查看未經測試的原因,恕我直言。

+0

謝謝dty,同意你我也不想測試SystemExit,我想單元測試方法exitWhenQuitDetected,基本上模擬了SysytemExit,BufferedReader等類,並驗證SystemExit.exit(0)方法確實在看到「退出「輸入。 –

3

你應該包括PowerMockito瓶子到你的項目,而不僅僅是香草Mockito。 Powermock庫專爲模擬靜態和/或最終類和方法而設計。

以下this blog post包含描述與您的類似場景的示例代碼。

基本上你需要一個測試類與此類似...

@RunWith(PowerMockRunner.class) 
@PrepareForTest({System.class, ClassToTest.class}) 
public class SystemExitTest { 

    @Test 
    public void shouldCallSystemExit() { 

     PowerMockito.mockStatic(System.class); 

     ClassToTest.methodToTest(); 

     PowerMockito.verifyStatic(); 

     System.exit(0); 

     System.out.println("If this message displays them System.exit() was mocked successfully"); 
    }  
} 

鑑於這種簡單的實現類...的技術解決方案

public class ClassToTest { 

    public static void methodToTest() { 
     // do some stuff 
     System.exit(0); 
    } 
} 
0

大量被提供。我想指出另一個角度:

這段代碼不應該被單元測試。

從單元測試中獲得的最大收穫是將它們應用於複雜的業務代碼時,尤其是具有大量分支時。

在代碼微不足道的情況下,我會建議不要編寫單元測試,因爲它只是沒有足夠高的投資回報。你的情況實際上加劇了我的觀點,想到你測試簡單的代碼所需的努力量,並將其與增益進行比較。這是否值得我們付出努力。這是否真的讓你更信任你自己的代碼?

+0

嗯,我+1了這個,因爲我認爲這個問題是關於'SystemExit'類的 - 正如你所說的那樣,不應該被測試。但'exitWhenQuitDetected'方法有'while'和'if' - 所以它應該被測試。問題在於該方法是「靜態」的。我會很快發佈一個答案,解釋如何最好地測試這個。 –

相關問題