2010-01-30 100 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