Java >> Java チュートリアル >  >> Tag >> assert

JUnit を使用したログ メッセージのアサート

1.はじめに

このチュートリアルでは、生成されたログを JUnit テストでカバーする方法について説明します .

slf4j-api を使用します そしてログバック 実装 ログ アサーションに使用できるカスタム アペンダーを作成します .

2. Maven の依存関係

始める前に、logback を追加しましょう 依存。 slf4j-api をネイティブに実装しているため 、Maven推移性によって自動的にダウンロードされ、プロジェクトに挿入されます:

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>. 
    <version>1.2.6</version>
</dependency>

AssertJ テスト時に非常に便利な機能を提供するので、その依存関係をプロジェクトにも追加しましょう:

<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <version>3.15.0</version>
    <scope>test</scope>
</dependency>

3.基本的なビジネス機能

それでは、テストのベースとなるログを生成するオブジェクトを作成しましょう。

BusinessWorker オブジェクトは 1 つのメソッドのみを公開します。このメソッドは、各ログ レベルで同じ内容のログを生成します。この方法は実際にはあまり役に立ちませんが、テスト目的には十分に役立ちます:

public class BusinessWorker {
    private static Logger LOGGER = LoggerFactory.getLogger(BusinessWorker.class);

    public void generateLogs(String msg) {
        LOGGER.trace(msg);
        LOGGER.debug(msg);
        LOGGER.info(msg);
        LOGGER.warn(msg);
        LOGGER.error(msg);
    }
}

4.ログのテスト

ログを生成したいので、logback.xml を作成しましょう。 src/test/resources のファイル フォルダ。できるだけシンプルにして、すべてのログを CONSOLE にリダイレクトしましょう アペンダー:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>
                %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n
            </Pattern>
        </layout>
    </appender>

    <root level="error">
        <appender-ref ref="CONSOLE"/>
    </root>
</configuration>

4.1. MemoryAppender

では、ログをメモリに保持するカスタム アペンダーを作成しましょう。 . ListAppender を拡張します そのログバック オファー 、いくつかの便利な方法でそれを充実させます:

public class MemoryAppender extends ListAppender<ILoggingEvent> {
    public void reset() {
        this.list.clear();
    }

    public boolean contains(String string, Level level) {
        return this.list.stream()
          .anyMatch(event -> event.toString().contains(string)
            && event.getLevel().equals(level));
    }

    public int countEventsForLogger(String loggerName) {
        return (int) this.list.stream()
          .filter(event -> event.getLoggerName().contains(loggerName))
          .count();
    }

    public List<ILoggingEvent> search(String string) {
        return this.list.stream()
          .filter(event -> event.toString().contains(string))
          .collect(Collectors.toList());
    }

    public List<ILoggingEvent> search(String string, Level level) {
        return this.list.stream()
          .filter(event -> event.toString().contains(string)
            && event.getLevel().equals(level))
          .collect(Collectors.toList());
    }

    public int getSize() {
        return this.list.size();
    }

    public List<ILoggingEvent> getLoggedEvents() {
        return Collections.unmodifiableList(this.list);
    }
}

MemoryAppender クラスは List を処理します ロギング システムによって自動的に入力されます。

幅広いテスト目的をカバーするために、さまざまなメソッドを公開しています:

  • reset() – リストをクリアします
  • contains(msg, level)true を返します リストに ILoggingEvent が含まれている場合のみ 指定されたコンテンツと重大度レベルに一致する
  • countEventForLoggers(loggerName)ILoggingEvent の数を返します 名前付きロガーによって生成
  • search(msg)リストを返します ILoggingEvent の 特定のコンテンツに一致
  • search(msg, level)リストを返します ILoggingEvent の 指定されたコンテンツと重大度レベルに一致する
  • getSize()ILoggingEvent の数を返します
  • getLoggedEvents()ILoggingEvent の変更不可能なビューを返します 要素

4.2.単体テスト

次に、ビジネス ワーカー用の JUnit テストを作成しましょう。

MemoryAppender を宣言します フィールドとして、プログラムでログ システムに挿入します。次に、appender を開始します。

テストでは、レベルを DEBUG に設定します :

@Before
public void setup() {
    Logger logger = (Logger) LoggerFactory.getLogger(LOGGER_NAME);
    memoryAppender = new MemoryAppender();
    memoryAppender.setContext((LoggerContext) LoggerFactory.getILoggerFactory());
    logger.setLevel(Level.DEBUG);
    logger.addAppender(memoryAppender);
    memoryAppender.start();
}

これで、BusinessWorker をインスタンス化する簡単なテストを作成できます。 クラスを作成し、generateLogs を呼び出します 方法。次に、それが生成するログに対してアサーションを行うことができます:

@Test
public void test() {
    BusinessWorker worker = new BusinessWorker();
    worker.generateLogs(MSG);
        
    assertThat(memoryAppender.countEventsForLogger(LOGGER_NAME)).isEqualTo(4);
    assertThat(memoryAppender.search(MSG, Level.INFO).size()).isEqualTo(1);
    assertThat(memoryAppender.contains(MSG, Level.TRACE)).isFalse();
}

このテストでは、MemoryAppender の 3 つの機能を使用します :

  • 4 つのログが生成されました。重大度ごとに 1 つのエントリが存在し、トレース レベルがフィルタリングされています
  • 内容 メッセージ を含む 1 つのログ エントリのみ INFO の重大度レベル
  • コンテンツメッセージを含むログエントリがありません 重大度 TRACE

大量のログを生成するときに、同じテスト クラス内でこのクラスの同じインスタンスを使用する場合、メモリ使用量が増加します。 MemoryAppender.clear() を呼び出すことができます 各テストの前にメソッドを使用してメモリを解放し、OutOfMemoryException を回避します .

この例では、保持されるログの範囲を LOGGER_NAME に縮小しました。 「com.baeldung.junit.log」として定義したパッケージ 」。 LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME) ですべてのログを保持できる可能性があります。 ただし、大量のメモリを消費する可能性があるため、可能な限りこれを避ける必要があります .

5.結論

このチュートリアルでは、単体テストでログ生成をカバーする方法を示しました .

いつものように、コードは GitHub にあります。


Java タグ