JUnitでログが出力されているかをテストする
こんばんよ~
すっかり日にちがあいてしまいました。
今週忙しくて…っていう甘え。
昨日は先輩達と夕飯食べてきたよ~
ざぼん美味しかったよざぼん。
あ。先週シルバーとってきました。
90はいったでしょとか思ってたけど83しか取れてなかった。
ぐやじい。
ということで、今日はJunitを使ってテストをする際、
「ログが出力されているのかを確認(テスト)する方法」
についてまとめたいと思うよ。
と、その前に、今回のプロジェクトでは
ログ生成ツールにlogbackを使っていたんだけど、
logbackとlog4jってなにが違うのかな~
と思って、少し調べてみた。
まず、Javaのロガーの構成(jar)を簡単にまとめるとこんな感じ。
・インターフェース
→ログを出力するための機能一覧を提供している
・commons-logging
・slf4j
・(上記インターフェースに対する)実装
・log4j
・logback
・java.util.logging
logbackはlog4jの開発者が作った後継的な実装なんだって。
インターフェースに対する実装がしょぼいと、処理が遅かったり、
そもそもインターフェースに対する実装が未実装だったりするらしい。
ちなみに、今まではcommons-logging+log4jがトレンドだったらしいけど
最近はslf4j+logbackがトレンドらしい。
そうそう、で、結局log4jとlogbackの違いはというと、
以下のような点でslf4j+logbackが優れているんだって。
1.ログ出力時のパフォーマンス向上
2.ログ設定を起動中に再読み込みする設定が可能
3.デバッグログ出力時、isDebugEnabledメソッドでの囲みが不要
(引用元:http://d.hatena.ne.jp/kimutansk/20121123/1353686394)
調べながらへぇ~ってなってる。
ロガーの種類についてはこの辺にして、
いよいよ本題にうつっていくよ。
「ログが出力されているのかを確認する方法」について。
って言ってもソースコードのっけるだけなんだけど…
log4jを使用してログを出力している場合
@Test public void test() { StringWriter writer = new StringWriter(); WriterAppender appender = new WriterAppender(new PatternLayout("%p, %m%n"),writer); LogManager.getRootLogger().addAppender(appender); LogManager.getRootLogger().setAdditivity(false); try{ /** 何かしらのログを出力する処理 */ /** エラーログのテスト */ String logString = writer.toString(); assertThat(logString, containsString(" 確認したいログメッセージ ")); }finally{ LogManager.getRootLogger().removeAppender(appender); LogManager.getRootLogger().setAdditivity(true); } }
logbackを使用してログを出力している場合
@Test public void test() { ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(ch.qos.logback.clasLogger.ROOT_LOGGER_NAME); @SuppressWarnings("unchecked") final Appender<ILoggingEvent> mockAppender = mock(Appender.class); when(mockAppender.getName()).thenReturn("MOCK"); root.addAppender(mockAppender); /** 何かしらのログを出力する処理 */ verify(mockAppender).doAppend(argThat(new ArgumentMatcher<LoggingEvent>() { @Override public boolean matches(Object argument) { return ((LoggingEvent)argument).getFormattedMessage().contains(" 確認したいログメッセージ "); } }));
こちらはMockito使ってますな。
ちなみに、
LoggerFactory.getLogger(ch.qos.logback.clasLogger.ROOT_LOGGER_NAME);
この部分、ロガーを指定しているんだけど、
rootロガーを使っていない場合は、
自分の使用しているロガー名を指定してあげないと動かない。
↓こっちじゃなくて
<root> <level value="WARN" /> <appender-ref ref="system" /> </root>
↓こっち使ってる時とか
<logger name="trace" level="INFO" additivity="false"> <appender-ref ref="trace.log" /> </logger>
ソースをなんとなくにしか理解せずコピ★ペした私は
自分がこの問題に引っかかっていることに気づかず、
小一時間程悩んでいました。
(先輩が一瞬で解決してくれました。)
ソースの引用元はhttp://qiita.com/sifueさんのQiita投稿記事。
ありがとうございました…
最後に雑談だけど、最近調べ物をしている時、
Stack OverFlowとかも見るようになったよ。
なんとなーく質問者の投稿記事見て、
自分と同じような問題でつまってる人見つけて、
回答者のソース見て「あーこんな感じか」とか思って
自分のコードに反映させてみたりして。
で、結果動いた時とかもう最高!
めっちゃ英語できた気分になる(そっち)
なんだかんだで毎日楽しく仕事してると思う今日このごろ。
ではでは。おやスヤァ