如何通过单元测试验证Logback ConsoleAppender的日志格式配置生效?
测试Logback日志格式与敏感数据掩码的方案
一、验证现有日志格式的单元测试
要捕获Logback输出的日志内容做断言,核心思路是自定义内存Appender(临时替代或追加到现有配置),把日志事件存到内存中,再取出验证格式是否符合预期。
1. 实现内存Appender
先写一个简单的内存Appender,用来捕获日志事件:
import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.UnsynchronizedAppenderBase; import java.util.ArrayList; import java.util.List; public class MemoryAppender extends UnsynchronizedAppenderBase<ILoggingEvent> { private final List<ILoggingEvent> events = new ArrayList<>(); @Override protected void append(ILoggingEvent event) { events.add(event); } public List<ILoggingEvent> getEvents() { return new ArrayList<>(events); } public void clear() { events.clear(); } }
2. 编写单元测试
用JUnit 5结合Logback API动态配置Appender,捕获日志后验证格式:
import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.LoggerContext; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import static org.junit.jupiter.api.Assertions.*; import java.util.regex.Pattern; public class LogbackFormatTest { private Logger targetLogger; private MemoryAppender memoryAppender; @BeforeEach void setUp() { // 替换成你项目中实际要测试的Logger targetLogger = (Logger) LoggerFactory.getLogger("com.yourproject.YourService"); // 初始化内存Appender并绑定到目标Logger LoggerContext loggerContext = targetLogger.getLoggerContext(); memoryAppender = new MemoryAppender(); memoryAppender.setContext(loggerContext); memoryAppender.start(); targetLogger.addAppender(memoryAppender); } @AfterEach void tearDown() { // 清理资源,避免影响其他测试 targetLogger.detachAppender(memoryAppender); memoryAppender.stop(); MDC.clear(); } @Test void testLogFormatMatchesConfiguration() { // 加入MDC参数测试%kvp字段 MDC.put("traceId", "abc123"); String testMsg = "test log content"; // 触发日志输出 targetLogger.info(testMsg); ILoggingEvent event = memoryAppender.getEvents().get(0); String formattedLog = event.getFormattedMessage(); // 用正则匹配动态部分(比如时间、线程名),固定部分直接校验 String logPatternRegex = "^\\d{2}:\\d{2}:\\d{2}\\.\\d{3} \\[.+\\] INFO com\\.yourproject\\.YourService -traceId=abc123- " + testMsg + "$"; assertTrue(Pattern.matches(logPatternRegex, formattedLog), "日志格式与配置不符"); // 也可以拆分字段单独验证 assertEquals("INFO", event.getLevel().toString()); assertEquals("com.yourproject.YourService", event.getLoggerName()); assertEquals(testMsg, event.getMessage()); } }
二、敏感数据掩码功能的测试
不管你是用自定义Converter还是TurboFilter实现敏感数据掩码(比如手机号、身份证号替换为****),测试逻辑和上面一致:捕获日志后验证敏感内容是否被正确替换。
示例测试代码
@Test void testSensitiveDataMasking() { String sensitiveIdCard = "110101199003074567"; // 触发包含敏感数据的日志 targetLogger.info("用户身份证:{}", sensitiveIdCard); ILoggingEvent event = memoryAppender.getEvents().get(0); String formattedLog = event.getFormattedMessage(); // 验证敏感数据已按规则掩码(示例规则:保留前6后4,中间替换为********) assertTrue(formattedLog.contains("用户身份证:110101********4567"), "敏感数据未正确掩码"); }
额外提示
- 如果是自定义Converter实现掩码,可以单独测试Converter逻辑:直接调用
convert方法传入敏感数据,验证输出结果,不用依赖Logback的Appender。 - 测试时要覆盖多种场景:空值、不符合规则的字符串、边界长度的敏感数据,确保掩码逻辑鲁棒。
内容的提问来源于stack exchange,提问作者Vitaly Gavrilchenko
相关产品推荐
相关产品推荐

