我有一个测试控制台应用程序的任务。我可以访问其中一个方法,但也想检查字符串格式化是否正常工作。
由于该方法不返回字符串,而是打印到控制台,有没有办法拦截打印的内容?
对这种东西进行测试甚至有意义吗?
我有一个测试控制台应用程序的任务。我可以访问其中一个方法,但也想检查字符串格式化是否正常工作。
由于该方法不返回字符串,而是打印到控制台,有没有办法拦截打印的内容?
对这种东西进行测试甚至有意义吗?
这是一个示例,说明如何捕获System.out的输出:
java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
System.setOut(new java.io.PrintStream(out));
System.out.println("Test output");
System.err.println("Out was: " + out.toString());
您可以使用System.setOut()
来重定向System.out.println
写入到一个PrintStream(OutputStream)
中。然后,您可以将该OutputStream写入字符串并进行测试。
测试的方法是使用“输出”抽象而不是直接打印到“system.out”来进行良好的设计。例如:
interface Output {
void print(String data);
}
然后你将这个依赖注入到需要向输出发送信息的类中:
class MyProgram {
private Output out;
public MyProgram(Output output) {
this.out = output;
}
public doSomething() {
// do something
out.print("i do something!);
}
}
然后你可以使用模拟对象(例如使用Mockito)轻松进行测试:
public void test_my_program() {
Output mockOutput = mock(Output.class);
MyProgram myProgram = new MyProgram(mockOutput);
myProgram.doSomething();
verity(mockOutput).print("do something!");
}
我没有验证代码,但它大致正确,我希望足够让你理解。总是如此,测试并不困难,困难的是设计良好可测试的代码,在这里我们只使用抽象和依赖注入两个面向对象的基本原则。
这段代码的真正优势在于现在它不再与“System.out”绑定,例如,您可以在Web应用程序中使用此类,如果您愿意,例如制作一个输出实现,通过websocket与Web客户端通信。这是另一个面向对象的原则,您的类现在是“开放-关闭”的,您可以添加功能(websocket疯狂的例子:P)而不修改您的实际代码。