6

I have a method that calls a method called "burn" inside that throws a data exception, and if so, then it is caught in a try/catch block and logs to a logger. The class is using the annotation @Slf4j however, and lombok.extern.slf4j:

@Slf4j
public class MyClass {

 private void myMethod(Type parameter) throws Exception {
     try {
        dataGateway.burn(id);
         }
     catch {
        log.error("Failed to burn({})",id);
        }
  }

I have already mocked the datagateway and have it throwing an exception when burn is called, I know the exception is caught but how do I use verify to assert the logger was called with .error?? DateGateway dBMock = mock(DateGateway.class);

when(dBMock.burn(anyString())).thenReturn(new DataException("exception"));
ennth
  • 1,698
  • 5
  • 31
  • 63

2 Answers2

5

I found a nice solution to this problem here: https://www.jvt.me/posts/2019/09/22/testing-slf4j-logs/

The solution was to add a log appender to the class you want to test and then just read what has been logged from that appender.

Here is a generic method to add and return an appender for a specific class:

private ListAppender<ILoggingEvent> getListAppenderForClass(Class clazz) {
    Logger logger = (Logger) LoggerFactory.getLogger(clazz);
    ListAppender<ILoggingEvent> loggingEventListAppender = new ListAppender<>();
    loggingEventListAppender.start();
    logger.addAppender(loggingEventListAppender);
    return loggingEventListAppender;
}

In your case you could then use this appender like this in your test to verify that your specific log row was invoked:

final ListAppender<ILoggingEvent> listAppenderForClass = getListAppenderForClass(CardApi.class);
org.assertj.core.api.Assertions.assertThat(listAppenderForClass.list)
                .extracting(ILoggingEvent::getFormattedMessage)
                .anyMatch((Predicate<String>) s -> s.startsWith("Failed to burn"));
Fredrik
  • 487
  • 5
  • 12
3

You can try library: https://www.simplify4u.org/slf4j-mock/

It is also work with lombok annotation.

With slf4j-mock you don't need special code for preparing logger mock.

Slawomir Jaranowski
  • 7,381
  • 3
  • 25
  • 33