Log4j2 模拟 Appender

Dev*_*per 5 java junit log4j log4j2

我有一个课程,我在其中获取了所有属性,并在登录之前隐藏了它们的密码。

@Override
public void afterPropertiesSet() throws Exception {
    Properties loadedProperties = this.mergeProperties();
    loadedProperties.entrySet().stream().forEach(singleProperty -> {
        String key = singleProperty.getKey().toString();
        String value = HIDDEN_VALUE;

        if (!Arrays.stream(PASSWORD_PATTERNS).anyMatch(pattern -> key.toLowerCase().contains(pattern))) {
            value = singleProperty.getValue().toString();                  
        }

        logger.info("LoadedProperty: "+ key +"=" + value);
    });
}
Run Code Online (Sandbox Code Playgroud)

我已经迁移到 log4j2 并想测试这个类,检查 log4j2 的输出。它目前使用 log4j 并且有效,但是当我迁移到 log4j2 时,我得到

需要但未调用:mockAppender.append(); -> 在 com.comp.spmConf.ExceptionLoggerTest.verifyErrorMessages(ExceptionLoggerTest.java:87)

但是,还有其他与此模拟的交互:mockAppender.getName(); -> 在 org.apache.logging.log4j.core.config.AbstractConfiguration.addLoggerAppender(AbstractConfiguration.java:675)

mockAppender.getName(); -> 在 org.apache.logging.log4j.core.config.AppenderControl.(AppenderControl.java:51)

这是我的 log4j1 测试类:

import org.apache.log4j.Appender;
import org.apache.log4j.LogManager;
import org.apache.log4j.spi.LoggingEvent;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;

import java.util.Properties;

@RunWith(MockitoJUnitRunner.class)
public class SpmPropertyTracerTest {

@Mock
private Appender appenderMock;

@Captor
private ArgumentCaptor captorLoggingEvent;

private SpmPropertyTracer tracer;

@Before
public void setup() {
    LogManager.getRootLogger().addAppender(appenderMock);
    tracer = new SpmPropertyTracer();
}

@After
public void teardown() {
    LogManager.getRootLogger().removeAppender(appenderMock);
}

@Test
public void printPropertiesTest() throws Exception{
    String key1 = "Foo";
    String val1 = "True";
    Properties properties = new Properties();
    properties.setProperty(key1, val1);
    tracer.setProperties(properties);
    String expectedString = String.format("LoadedProperty: %s=%s", key1, val1);
    tracer.afterPropertiesSet();
    Mockito.verify(appenderMock).doAppend((LoggingEvent)captorLoggingEvent.capture());
    LoggingEvent loggingEvent = (LoggingEvent) captorLoggingEvent.getValue();
    assert expectedString.equals(loggingEvent.getRenderedMessage());
}

}
Run Code Online (Sandbox Code Playgroud)

这是我的 log4j2 测试类,我在 log4j 到 log4j2 迁移中做错了什么吗?

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import java.util.Properties;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;



@RunWith(MockitoJUnitRunner.class)
public class TestClass {
@Mock
private Appender mockAppender;
@Captor
private ArgumentCaptor<LogEvent> captorLoggingEvent;

private SpmPropertyTracer tracer;

private Logger logger;

private LogEvent logEvent;

@Before
public void setup() {
    // prepare the appender so Log4j likes it
    when(mockAppender.getName()).thenReturn("MockAppender");
    when(mockAppender.isStarted()).thenReturn(true);
    when(mockAppender.isStopped()).thenReturn(false);

    logger = (Logger)LogManager.getLogger(SpmPropertyTracer.class);
    logger.addAppender(mockAppender);
    logger.setLevel(Level.INFO);

    tracer = new SpmPropertyTracer();
}

@After
public void tearDown() {
    // the appender we added will sit in the singleton logger forever
    // slowing future things down - so remove it
    logger.removeAppender(mockAppender);
}

@Test
public void loggingIsCaptured() throws Exception {
    String key1 = "Foo";
    String val1 = "True";
    Properties properties = new Properties();
    properties.setProperty(key1, val1);
    tracer.setProperties(properties);
    String expectedString = String.format("LoadedProperasdfty: %s=%s", key1, val1);
    tracer.afterPropertiesSet();
    verifyErrorMessages(expectedString);
}


// handy function to inspect the messages sent to the logger
private void verifyErrorMessages(String ... messages) {
    verify(mockAppender, times(messages.length)).append((LogEvent)captorLoggingEvent.capture());

    int i=0;
    for(LogEvent loggingEvent:captorLoggingEvent.getAllValues()) {
        assertEquals(messages[i++], loggingEvent.getMessage().getFormattedMessage());
    }
}
Run Code Online (Sandbox Code Playgroud)

Dev*_*per 2

父项目引入了 log4j 依赖项,因此 slf4j 与 log4j 绑定,而不是 log4j2,这就是未调用追加方法的原因。删除该依赖项修复了我的错误。