单元测试ConsoleAppender log4j

时间:2013-06-02 18:39:42

标签: java junit log4j

我正在尝试在内部更改自定义异常的布局。要进行单元测试,我希望捕获控制台输出。我之前已经捕获了控制台输出,但我之前使用的方法似乎没有log4j的预期结果。

如果我想捕获控制台输出,我会使用:

    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
    final PrintStream printStream = new PrintStream(baos);
    System.setOut(printStream);
    System.out.println("Hello world!");
    final String consoleOutput = baos.toString();

consoleOutput的值将是“Hello World!”。

如果我使用:

将此应用于log4j
    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
    final PrintStream printStream = new PrintStream(baos);
    System.setOut(printStream);
    LOGGER.debug("Simple message");
    final String consoleOutput = baos.toString();

consoleOutput为空。查看ConsoleAppender的javadoc,我看到:

  

默认目标是System.out。

如果我将我的代码更改为仅包含该行:

   LOGGER.debug("Simple message");

我在控制台中看到了预期的结果:

  

2013-06-02 19:49:46,818 DEBUG [com.parlance.LoggingTest] - 简单   消息

所以我假设这会起作用,但显然已经错过了一些东西而且一直在摸不着头脑!

更新

我刚尝试了一些东西,如果我将记录器类的创建更改为在我调用System.setOut之后,它似乎可以工作:

  final ByteArrayOutputStream baos = new ByteArrayOutputStream();
  final PrintStream printStream = new PrintStream(baos);
  System.setOut(printStream);
  final Logger logger = Logger.getLogger(LoggingTest.class);
  logger.debug("Simple message");
  final String consoleOutput = baos.toString();

这具有预期的效果,但如果我希望Logger是静态的,则不是很好。任何想法为什么会发生以及如何在不以这种方式声明记录器的情况下解决原始问题?

1 个答案:

答案 0 :(得分:1)

似乎在初始化log4j之后调用了System.setOut。 log4j使用System.out的值进行初始化(它将保留对它的引用)。你可以通过在log4j之前调用System.setOut来解决它。正如你所说的那样。

对于静态记录器,它变得更难;你可以使用选项

-Dlog4j.defaultInitOverride=true

这意味着log4j不会自动初始化,但您仍需要安排在第一个记录器之前调用System.setOut

有关详细信息,请参阅Short introduction to log4j (section Default Initialization Procedure)