0

我正在尝试在内部更改自定义异常的布局。为了对此进行单元测试,我希望捕获控制台输出。我之前已经捕获了控制台输出,但是我之前使用的方法似乎没有 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();

控制台输出为空。查看 ConsoleAppender 的 javadoc 我看到:

默认目标是 System.out。

如果我将代码更改为仅包含以下行:

   LOGGER.debug("Simple message");

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

2013-06-02 19:49:46,818 调试 [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 是静态的,那就不是很好。任何想法为什么会发生这种情况以及如何在不以这种方式声明记录器的情况下解决原始问题?

4

1 回答 1

1

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

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

-Dlog4j.defaultInitOverride=true

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

有关更多信息,请参阅log4j 简介(默认初始化过程部分)

于 2013-06-03T07:37:34.810 回答