2010-01-30 63 views
24

我正在使用JUnit編寫集成測試來自動化測試基於控制檯的應用程序。應用程序是功課,但這部分不是功課。我想讓這些測試自動化以提高生產力 - 我不想回去重新測試已經測試過的應用程序部分。 (使用單元測試的標準原因)Java,Junit - 捕獲單元測試中使用的標準輸入/輸出

無論如何,我找不到或找到一篇關於捕獲輸出的文章,以便我可以對其執行assertEquals或提供自動輸入。我不在乎輸出/輸入是否進入控制檯/輸出窗格。我只需要執行測試並驗證輸出是預期的輸入。

任何人都有文章或代碼來幫助解決這個問題。

+0

@dfa,我不同意。它確實相似但不同。 –

+0

...授予答案是一樣的... –

+1

另一個線程現在有一個更好的答案。它涉及使用jUnit StandardOutputStreamLog系統規則。還有stderr和stdin的系統規則。 –

回答

38

使用System.setOut()(和System.setErr())將輸出重定向到任意打印流 - 可以是以編程方式讀取的打印流。

例如:

final ByteArrayOutputStream myOut = new ByteArrayOutputStream(); 
System.setOut(new PrintStream(myOut)); 

// test stuff here... 

final String standardOutput = myOut.toString(); 
+1

因此,簡單地去'PrintStream _out = System.out;'不起作用? –

+0

它會 - 即你有一個對現有輸出流的引用 - 但是你不能從中讀取任何東西,因爲在普通的'PrintStream'接口上沒有合適的方法來這樣做。該技術涉及將輸出設置爲您知道如何讀取的特定打印流。 –

7

System類有方法setIn()setOut()setErr(),允許用戶設置的標準輸入,輸出和錯誤流,例如到您可以隨意檢查的ByteArrayOutputStream

1

這裏是解決方案來代替ByteArrayOutputStream。它沒有添加任何東西到System.setOut的想法。相反,我想分享比捕獲ByteArrayOutputStream更好的實現。我更喜歡僅捕獲選定的信息,並讓所有日誌消息在登錄時出現在控制檯中,而不是將所有內容都捕獲到一個balckbox(具有哪種大小?)供以後處理。

/** 
* Once started, std output is redirected to this thread. 
* Thread redirects all data to the former system.out and 
* captures some strings.*/ 
static abstract class OutputCaputre extends Thread { 

    // overrdie these methods for System.err 
    PrintStream getDownstream() { return System.out;} 
    void restoreDownstream() { System.setOut(downstream);} 

    // will be called for every line in the log 
    protected abstract void userFilter(String line); 

    final PrintStream downstream; 
    public final PipedInputStream pis; 
    private final PipedOutputStream pos; 
    OutputCaputre() throws IOException { 
     downstream = getDownstream(); 

     pos = new PipedOutputStream(); 
     pis = new PipedInputStream(pos); 
     System.setOut(new PrintStream(pos)); 

     start(); 
    } 

    public void run() { 
     try { 
      BufferedReader br = new BufferedReader(new InputStreamReader(pis)); 

      // once output is resotred, we must terminate 
      while (true) { 
       String line = br.readLine(); 
       if (line == null) { 
        return; 
       } 
       downstream.println(line); 
       userFilter(line); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void terminate() throws InterruptedException, IOException { 
     restoreDownstream(); // switch back to std 
     pos.close(); // there will be no more data - signal that 
     join(); // and wait until capture completes 
    } 
}; 

以下是使用類的一個示例:

OutputCaputre outputCapture = new OutputCaputre() { 
    protected void userFilter(String line) { 
     downstream.println("Capture: " + line); 
    }  
}; 
System.out.println("do you see me captured?"); 
// here is your test  
outputCapture.terminate(); // finally, stop capturing