Mockitoを利用してUnitテストでログメッセージを検証する方法を記載します。
環境
主なライブラリは以下
ライブラリ | バージョン |
---|---|
Junit | 4.12 |
mockito | 1.10.19 |
log4j | 2.6.2 |
Mavenを利用しています。詳細なバージョンなどは以下のリンク先を参照してください。
pom.xml
テスト対象
テスト対象のクラスは以下の通りです。sayHelloメソッドを呼び出すと、ログにメッセージをINFOレベルで出力します。ログ出力はlog4jを利用しています。
class HelloWorld {
private Logger logger = LogManager.getLogger(this);
void sayHello(String name) {
logger.info("Hello " + name);
}
}
テストコード
ログメッセージを取得するためにAppenderのMockオブジェクトが必要となります。また、Mockオブジェクトから引数の値を取得するためのArgumentCaptorも準備します。
@Mock
private Appender mockAppender;
@Captor
private ArgumentCaptor<LogEvent> logCaptor;
上記で準備したAppenderオブジェクトをlog4jに設定します。このとき、mockAppenderオブジェクトがlog4jから呼び出された際にAppenderとして動作するようにMockitoで返却する値を指定しておきます。
Mockito.reset(mockAppender);
// Appenderの名前を設定
Mockito.when(mockAppender.getName()).thenReturn("MockAppender");
// Appenderとして利用できる準備ができていることを設定(下2行)
Mockito.when(mockAppender.isStarted()).thenReturn(true);
Mockito.when(mockAppender.isStopped()).thenReturn(false);
// ROOTロガーを取り出し、Appenderの設定を行う。
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
loggerConfig.setLevel(Level.INFO);
loggerConfig.addAppender(mockAppender, Level.INFO, null);
ctx.updateLoggers();
実際のテストコードは以下となります。Appenderのappendメソッドからメッセージを取り出します。呼び出し回数もチェックできます。今回は明らかに1回のため1と指定しています。
@Test
public void outputLogMessage() {
String name = "World";
HelloWorld helloWorld = new HelloWorld();
helloWorld.sayHello(name);
Mockito.verify(mockAppender, Mockito.times(1)).append(logCaptor.capture());
String message = logCaptor.getValue().getMessage().getFormattedMessage();
Level level = logCaptor.getValue().getLevel();
assertThat(message, is("Hello " + name));
assertThat(level, is(Level.INFO));
}
まとめ
Mockitoを利用してAppenderのappendオブジェクトの引数を取得することで、ログメッセージの検証を行う方法を記載しました。これにより、メッセージだけでなく、ログレベルの検証も可能となります。
この方法を知る前は、ログファイルに出力された文字列を解析していたため、とても苦労しました。
もうそんな苦労とはおさらばです。
コード一式
以下にソースコードを公開しています。試しに動かしたい方は参照してみてください。