如何保存输出Log4j在JUnit测试中发送到STDOUT?

Ste*_*han 2 java junit redirect stdout junit4

我正在编写测试,我想通过测试方法捕获STDOUT上发送的消息.这是我的代码:

@Test
public void testAction() throws IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException,
        CmdLineException, IOException {
    PrintStream originalSTDOUT = System.out;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    PrintStream ps = new PrintStream(baos);

    try {
        System.setOut(ps);

        // Call to the method that will print text to STDOUT...

        ps.flush();
        String batchLog = baos.toString("UTF-8");
        assertTrue("Invalid exception text !", batchLog.contains("my expected text..."));
    } finally {
        System.setOut(originalSTDOUT);//Restore original STDOUT
        originalSTDOUT.write(baos.toByteArray());// Write back to STDOUT, even if I comment this line, outputs go to STDOUT... 

        ps.close();
    }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,batchLog虽然我仍然可以读到STDOUT的预期文本,但它总是空的.

将文本打印到STDOUT的方法实际上会捕获异常.然后将它传递给Logger如下所示:

log.warn("发生错误:",e);

e我在测试中调用的方法中引发的异常在哪里.

Logger使用这个附加器打印其消息:org.apache.log4j.ConsoleAppender.没有特殊配置应用于此appender.

我错过了什么?

PS:这个SO答案很有意思但它对我不起作用,因为ConsoleAppender它已经在StandardOutputStreamLog规则可以行动之前创建了.

Java 6
Junit 4.10

Ste*_*han 8

我终于解决了我的问题!

我的第一次尝试是错误的,因为@Joni在他的评论中指出,我将STDOUT重定向太晚了:ConsoleAppender已经创建了.

因为,异常消息是由a处理的Logger,所以我决定添加一个WriterAppenderStringWriter它支持的消息来获取消息.

这是我的工作解决方案:

@Test
public void testAction() throws IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException,
        CmdLineException, IOException {

        // Setup WriterAppender
        Writer w = new StringWriter();
        Layout l = new PatternLayout("%m%n");

        WriterAppender wa = new WriterAppender(l, w);
        wa.setEncoding("UTF-8");
        wa.setThreshold(Level.ALL);
        wa.activateOptions();// WriterAppender does nothing here, but I like defensive code...

        // Add it to logger
        Logger log = Logger.getLogger(ExceptionHandler.class);// ExceptionHandler is the class that contains this code : `log.warn("An error has occured:", e);'
        log.addAppender(wa);

        try {
             // Call to the method that will print text to STDOUT...

             String batchLog = w.toString();
             assertTrue("Invalid exception text !", batchLog.contains("my expected text..."));
        } finally {
             // Cleanup everything...
             log.removeAppender(wa);
             wa.close();
        }
}
Run Code Online (Sandbox Code Playgroud)