Skip to main content

Unit testing a static custom logger in Spring Boot and log4j2

Last time I wrote a post about how to unit test a custom logger with log4j2. Today I migrated another custom logger from log4j 1.x to log4j 2.x, but this time it was encapsulated in a Spring Boot component as a static class attribute.

Custom logger

You have a simple custom logger

public class SimpleCustomLogger {
  private final ExtendedLoggerWrapper log;

  private SimpleCustomLogger(final Logger log) {
    this.log = new ExtendedLoggerWrapper((AbstractLogger) log, 
                            log.getName(), log.getMessageFactory());
  }

  public static synchronized SimpleCustomLogger getLogger(final Class<?> clazz) {
    final Logger wrapped = LogManager.getLogger(clazz);
    return new SimpleCustomLogger(wrapped);
  }

  public void info(Object message) {
    if (log.isInfoEnabled()) {
      log.info(message);
    }
  }
}

which is used in a Spring Boot Component like so

import org.springframework.stereotype.Component;

@Component
public class CustomComponent
{
    private static SimpleCustomLogger logger = SimpleCustomLogger.getLogger(CustomComponent.class);

    public void doSomething() {
        logger.info("Hello from the Simple Custom Logger");
    }
}

The power of the ListAppender

The trick of the ListAppender showed in my last post works exactly the same here. It will listen to all the events that are happening to the logger it is attached to.

Here the log4j2.xml:

<Configuration status="DEBUG" name="TestCustomLogger">
<Appenders>
    <Console name="STDOUT">
        <PatternLayout pattern="%m%n"/>
    </Console>
    <List name="List1"/>
</Appenders>
<Loggers>
    <Root level="DEBUG">
        <AppenderRef ref="STDOUT"/>
        <AppenderRef ref="List1"/>
    </Root>
</Loggers>
</Configuration>

and here unit test:

@RunWith(SpringRunner.class)
@SpringBootTest
public class SimpleCustomLoggerTest {
  @Autowired
  CustomComponent component;

  @ClassRule
  public static LoggerContextRule context = new LoggerContextRule("log4j2.xml");
  private ListAppender listAppender;

  @Before
  public void setup(){
    listAppender = context.getListAppender("List1").clear();
  }

  @Test
  public void testCustomComponent() {
    // This will write something with the custom logger
    component.doSomething(); 
    // Retrieve the ListAppender
    final List<LogEvent> events = listAppender.getEvents();
    
    assertThat(events, hasSize(1));
    assertEquals("Custom logger is catched by the ListAppender",
        "Hello from the Simple Custom Logger",
        events.get(0).getMessage().getFormattedMessage());
  }
}

Unit testing a custom logger with log4j2 is really super simple.