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);
}
}