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();

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 を静的にしたい場合はあまり良くありません。なぜこれが起こるのか、ロガーをこのように宣言せずに元の質問に対処する方法はありますか?

4

1 に答える 1

1

System.setOutlog4jの初期化後に呼び出されているようです。log4j は の値を使用して初期化しますSystem.out(それへの参照を保持します)。System.setOutあなたが言ったように、log4jの前に呼び出すことで回避できます。

静的ロガーの場合はさらに難しくなります。オプションを使用できます

-Dlog4j.defaultInitOverride=true

これは、log4j が自動的に初期化されないことを意味しますがSystem.setOut、最初のロガーの前に呼び出されるように調整する必要があります。

詳細については、log4j の簡単な紹介 (セクション デフォルトの初期化手順) を参照してください。

于 2013-06-03T07:37:34.810 に答える