使用LogCaptor對日誌進行單元測試

1 爲什麼要對日誌進行單元測試

對代碼中打印的日誌,是否有必要通過單元測試保證日誌的格式、內容能夠被正確的修改?答案是在一般情況下都無需對日誌的格式、內容進行單元測試。那麼在什麼場景下,通過單元測試看護日誌的格式、內容是有必要的呢?在日誌作爲系統的輸入時(告警、統計系統等),爲了保證其他系統的正確運行,日誌的格式、內容保持不變就非常的有必要。還有一點就是這些作爲其他系統輸入的日誌和普通的信息、錯誤記錄日誌並沒有不同,在開發過程中往往修改起來比較隨意,增加單元測試可以提高相關日誌的重要性,再修改了日誌後可以及時通知其他系統進行調整,避免出現不必要的恐慌。

2 使用LogCaptor對日誌測試

文章中的源碼可以從:https://github.com/ctlove0523/java-samples 獲取

2.1 安裝LogCaptor

<dependency>
    <groupId>io.github.hakky54</groupId>
    <artifactId>logcaptor</artifactId>
    <version>2.7.8</version>
    <scope>test</scope>
</dependency>

LogCaptor項目地址:https://github.com/Hakky54/log-captor

2.2 測試類

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LogCaptorService {
    private static final Logger log = LoggerFactory.getLogger(LogCaptorService.class);

    public void commonLog() {
        log.debug("log captor debug log");
        log.info("log captor info log");
        log.warn("log captor warn log");
        log.error("log captor error log");
    }

    public void oddNumber(int number) {
        if (number % 2 == 1) {
            log.info("input is odd number");
        }

        log.info("input is even number");
    }

    public void logSwitch() {
        if (log.isDebugEnabled()) {
            log.debug("log enable debug");
        }

        log.info("log enable info");
    }
}

2.3 捕獲日誌

import static org.assertj.core.api.Assertions.assertThat;
import nl.altindag.log.LogCaptor;
import org.junit.Test;

public class CommonLogTest {

    @Test
    public void testCommonLog_should_logMessage() {
        LogCaptorService logCaptorService = new LogCaptorService();
        LogCaptor logCaptor = LogCaptor.forClass(LogCaptorService.class);

        logCaptorService.commonLog();

        assertThat(logCaptor.getDebugLogs()).containsExactly("log captor debug log");
        assertThat(logCaptor.getInfoLogs()).containsExactly("log captor info log");
        assertThat(logCaptor.getWarnLogs()).containsExactly("log captor warn log");
        assertThat(logCaptor.getErrorLogs()).containsExactly("log captor error log");
        assertThat(logCaptor.getLogs().size()).isEqualTo(4);
    }
}

2.4 重用LogCaptor

import static org.assertj.core.api.Assertions.assertThat;
import nl.altindag.log.LogCaptor;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class ReuseLogCaptorTest {
    private static LogCaptor logCaptor;

    @BeforeClass
    public static void init() {
        logCaptor = LogCaptor.forClass(LogCaptorService.class);
    }

    @Before
    public void cleanLogs() {
        logCaptor.clearLogs();
    }

    @AfterClass
    public static void close() {
        logCaptor.close();
    }

    @Test
    public void testOddNumber_should_logOddMsg_when_inputIsOddNumber() {
        LogCaptor logCaptor = LogCaptor.forClass(LogCaptorService.class);
        LogCaptorService logCaptorService = new LogCaptorService();

        logCaptorService.oddNumber(1);

        assertThat(logCaptor.getInfoLogs()).containsExactly("input is odd number");
        assertThat(logCaptor.getLogs().size()).isEqualTo(1);
    }

    @Test
    public void testOddNumber_should_logEvenMsg_when_inputIsEvenNumber() {
        LogCaptor logCaptor = LogCaptor.forClass(LogCaptorService.class);
        LogCaptorService logCaptorService = new LogCaptorService();

        logCaptorService.oddNumber(2);

        assertThat(logCaptor.getInfoLogs()).containsExactly("input is even number");
        assertThat(logCaptor.getLogs().size()).isEqualTo(1);
    }
}

2.5 測試帶有開關的日誌

import static org.assertj.core.api.Assertions.assertThat;
import nl.altindag.log.LogCaptor;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class LogSwitchTest {
    private static LogCaptor logCaptor;

    @BeforeClass
    public static void init() {
        logCaptor = LogCaptor.forClass(LogCaptorService.class);
    }

    @Before
    public void cleanLogs() {
        logCaptor.clearLogs();
    }

    @AfterClass
    public static void close() {
        logCaptor.close();
    }

    @Test
    public void testLogSwitch_should_notLogDebugMsg_when_logInfoOn() {
        LogCaptorService logCaptorService = new LogCaptorService();
        logCaptor.setLogLevelToInfo();

        logCaptorService.logSwitch();

        assertThat(logCaptor.getInfoLogs()).containsExactly("log enable info");
        assertThat(logCaptor.getLogs().size()).isEqualTo(1);
    }

    @Test
    public void testLogSwitch_should_logDebugMsg_when_logDebugOn() {
        LogCaptorService logCaptorService = new LogCaptorService();
        logCaptor.setLogLevelToDebug();

        logCaptorService.logSwitch();

        assertThat(logCaptor.getInfoLogs()).containsExactly("log enable info");
        assertThat(logCaptor.getDebugLogs()).containsExactly("log enable debug");
        assertThat(logCaptor.getLogs().size()).isEqualTo(2);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章