私は slf4j を使用しており、コードを単体テストして、特定の条件下で警告/エラー ログ メッセージが生成されることを確認したいと考えています。これらは厳密な単体テストにしたいので、ログメッセージが生成されることをテストするために、ファイルからロギング構成を取得する必要はありません。私が使用しているモッキング フレームワークは Mockito です。
13 に答える
特定の実装 (log4j など) に依存せずに slf4j をテストするには、この SLF4J FAQで説明されているように、独自の slf4j ロギング実装を提供できます。実装では、ログに記録されたメッセージを記録し、検証のために単体テストによって問い合わせることができます。
slf4j -testパッケージはまさにこれを行います。これは、ログに記録されたメッセージを取得するためのメソッドを提供するメモリ内 slf4j ロギングの実装です。
カスタムアペンダーで問題を解決できると思います。を実装するテスト アペンダーを作成し、アペンダーをorg.apache.log4j.Appender
に設定して、log4j.properties
テスト ケースの実行時にロードします。
そこからテスト ハーネスにコールバックするとappender
、ログに記録されたメッセージを確認できます
SLF4Jをモックする代わりに、テストする必要のある重要なロギング呼び出しを、より簡単にモックできる独自のメソッド内に配置することができます。
本当にSLF4Jをモックしたい場合は、サービスオブジェクトにモックロガーを挿入する代わりに、SLF4J側からモックロガーを提供できる独自のプロバイダーを作成できると思います。
この質問が投稿されてからしばらく経ちましたが、同様の問題に遭遇したばかりで、私の解決策が役立つかもしれません. @Zsolt によって提案されたソリューションに沿って、アペンダー、より具体的には Logback のListAppender
. ここにコードと構成を表示します (Groovy コードですが、Java に簡単に移植できます):
ログ アクセス用の Groovy クラス:
import ch.qos.logback.classic.Logger
import ch.qos.logback.classic.spi.LoggingEvent
import ch.qos.logback.core.read.ListAppender
import org.slf4j.LoggerFactory
class LogAccess {
final static String DEFAULT_PACKAGE_DOMAIN = Logger.ROOT_LOGGER_NAME
final static String DEFAULT_APPENDER_NAME = 'LIST'
final List<LoggingEvent> list
LogAccess(String packageDomain = DEFAULT_PACKAGE_DOMAIN, String appenderName = DEFAULT_APPENDER_NAME) {
Logger logger = (Logger) LoggerFactory.getLogger(packageDomain)
ListAppender<LoggingEvent> appender = logger.getAppender(appenderName) as ListAppender<LoggingEvent>
if (appender == null) {
throw new IllegalStateException("'$DEFAULT_APPENDER_NAME' appender not found. Did you forget to add 'logback.xml' to the resources folder?")
}
this.list = appender.list
this.clear()
}
void clear() {
list.clear()
}
boolean contains(String logMessage) {
return list.reverse().any { it.getFormattedMessage() == logMessage }
}
@Override
String toString() {
list.collect { it. getFormattedMessage() }
}
}
logback.xml 構成のサンプル:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- These 2 'includes' tags ensure regular springboot console logging works as usual -->
<!-- See https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-configure-logback-for-logging -->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<appender name="LIST" class="ch.qos.logback.core.read.ListAppender"/>
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="LIST" />
</root>
</configuration>
テスト:
LogAccess log = new LogAccess()
def expectedLogEntry = 'Expected Log Entry'
assert !log.contains(expectedLogEntry)
methodUnderTest()
assert log.contains(expectedLogEntry)
これを Groovy+Spock を使用する SpringBoot プロジェクトで使用しますが、これが Logback を使用する Java プロジェクトで機能しない理由がわかりません。