Java、Junit - 捕获用于单元测试的标准输入/输出
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2169330/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java, Junit - Capture the standard input / Output for use in a unit test
提问by Frank V
I'm writing integration tests using JUnit to automate the testing of a console based application. The application is homework but this part isn't the homework. I want to automate these tests to be more productive -- I don't want to have to go back and retest already tested parts of the application. (Standard reasons to use Unit tests)
我正在使用 JUnit 编写集成测试来自动化基于控制台的应用程序的测试。申请是作业,但这部分不是作业。我想自动化这些测试以提高效率——我不想回去重新测试应用程序中已经测试过的部分。(使用单元测试的标准理由)
Anyway, I can't figure out or find an article on capturing the output so that I can do assertEquals
on it nor providing automated input. I don't care if the output/input goes to the console/output pane. I only need to have the test execute and verify the the output is what is expected given the input.
无论如何,我无法弄清楚或找到有关捕获输出的文章,以便我可以对其进行assertEquals
处理,也无法提供自动输入。我不在乎输出/输入是否进入控制台/输出窗格。我只需要执行测试并验证输出是给定输入的预期结果。
Anyone have an article or code to help out with this.
任何人都有一篇文章或代码来帮助解决这个问题。
采纳答案by Andrzej Doyle
Use System.setOut()(and System.setErr()
) to redirect the output to an arbitrary printstream - which can be one that you read from programmatically.
使用System.setOut()(和System.setErr()
)将输出重定向到任意打印流 - 可以是您以编程方式读取的打印流。
For example:
例如:
final ByteArrayOutputStream myOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(myOut));
// test stuff here...
final String standardOutput = myOut.toString();
回答by Michael Borgwardt
The System
class has methods setIn()
, setOut()
and setErr()
that allow you to set the standard input, output and error streams, e.g. to a ByteArrayOutputStream
that you can inspect at will.
本System
类有方法setIn()
,setOut()
并setErr()
允许您的标准输入,输出和错误流,如设为ByteArrayOutputStream
您可以将检查。
回答by Val
Here is the solution in place of ByteArrayOutputStream. It does not add anything to the idea of System.setOut. Rather, I want to share the implementation that is better than capturing everything into ByteArrayOutputStream. I prefer to capture only selected information and let all log messages to appear in the console as they are logged rather than capturing everything into a balckbox (of which size?) for later processing.
这是替代 ByteArrayOutputStream 的解决方案。它不会为 System.setOut 的想法添加任何内容。相反,我想分享比将所有内容捕获到 ByteArrayOutputStream 中更好的实现。我更喜欢只捕获选定的信息,并让所有日志消息在记录时显示在控制台中,而不是将所有内容捕获到一个黑匣子(大小?)中以供以后处理。
/**
* 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
}
};
Here is an example of using the class:
以下是使用该类的示例:
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