我需要为一个设计很差的旧应用程序编写JUnit测试,并将大量错误消息写入标准输出 . 当 getResponse(String request)
方法行为正确时,它返回XML响应:
@BeforeClass
public static void setUpClass() throws Exception {
Properties queries = loadPropertiesFile("requests.properties");
Properties responses = loadPropertiesFile("responses.properties");
instance = new ResponseGenerator(queries, responses);
}
@Test
public void testGetResponse() {
String request = "<some>request</some>";
String expResult = "<some>response</some>";
String result = instance.getResponse(request);
assertEquals(expResult, result);
}
但是当它得到格式错误的XML或者不理解请求时它会返回 null
并将一些内容写入标准输出 .
有没有办法在JUnit中断言控制台输出?要 grab 像这样的案例:
System.out.println("match found: " + strExpr);
System.out.println("xml not well formed: " + e.getMessage());
12 回答
使用ByteArrayOutputStream和System.setXXX很简单:
样本测试用例:
我使用此代码来测试命令行选项(断言-version输出版本字符串等)
Edit: 此答案的先前版本在测试后称为
System.setOut(null)
;这是NullPointerExceptions评论者引用的原因 .我知道这是一个旧线程,但是有一个很好的库可以做到这一点:
System Rules
来自文档的示例:
它还允许您捕获
System.exit(-1)
以及命令行工具需要测试的其他内容 .您可以通过setOut()(以及
in
和err
)设置System.out打印流 . 你能将它重定向到记录到字符串的打印流,然后检查它吗?这似乎是最简单的机制 .(我会在某个阶段提倡将应用程序转换为一些日志框架 - 但我怀疑你已经意识到了这一点!)
我不会重定向
System.out
,而是通过传递PrintStream
作为协作者然后在 生产环境 中使用System.out
并在测试中使用Test Spy来重构使用System.out.println()
的类 . 也就是说,使用依赖注入来消除标准输出流的直接使用 .In Production
In the Test
Discussion
这样,通过简单的重构,可以测试被测试的类,而无需使用系统规则间接重定向标准输出或模糊拦截 .
稍微偏离主题,但是如果有些人(像我这样,当我第一次找到这个帖子时)可能对通过SLF4J捕获日志输出感兴趣,commons-testing的JUnit
@Rule
可能会有所帮助:Disclaimer :
我开发了这个库,因为我找不到适合自己需要的解决方案 .
目前只有
log4j
,log4j2
和logback
的绑定可用,但我很乐意添加更多内容 .@dfa答案很棒,所以我更进一步,以便测试输出块 .
首先,我使用方法
captureOutput
创建了TestHelper
,它接受了烦人的类CaptureTest
. captureOutput方法执行设置和拆除输出流的工作 . 当调用CaptureOutput
的test
方法的实现时,它可以访问测试块的输出生成 .TestHelper的来源:
请注意,TestHelper和CaptureTest在同一文件中定义 .
然后在测试中,您可以导入静态captureOutput . 以下是使用JUnit的示例:
如果您使用的是Spring Boot(您提到了're working with an old application, so you probably aren'但它可能对其他人有用),那么您可以按以下方式使用 org.springframework.boot.test.rule.OutputCapture :
您不希望重定向system.out流,因为它重定向到整个JVM . 在JVM上运行的任何其他东西都可能搞砸了 . 有更好的方法来测试输入/输出 . 查看存根/模拟 .
基于@dfa's answer和another answer that shows how to test System.in,我想分享我的解决方案,为程序提供输入并测试其输出 .
作为参考,我使用JUnit 4.12 .
假设我们有这个程序简单地将输入复制到输出:
要测试它,我们可以使用以下类:
我不会解释太多,因为我相信代码是可读的,我引用了我的资料 .
当JUnit运行
testCase1()
时,它将按照它们出现的顺序调用辅助方法:setUpOutput()
,因为@Before
注释provideInput(String data)
,来自testCase1()
getOutput()
,来自testCase1()
restoreSystemInputOutput()
,因为@After
注释我没有测试
System.err
因为我不需要它,但它应该很容易实现,类似于测试System.out
.使用_593122时,无法使用 system.out.println 或使用 logger api 直接打印 . 但是如果你想检查任何值,那么你就可以使用了
它将抛出以下断言错误:
你的值应该是21.92,现在如果你将使用下面的值进行测试,你的测试用例将会通过 .
出去
为了错误
完整的JUnit 5示例测试
System.out
(替换when部分):