In many case we want to test if our application logging is implemented in proper way. This is another easy way to testing what our application logs when we use slf4j framework.

Using slf4j-mock we can mock all logger and assert it as we do with other mocked method.

Feature of library:

  • Mockito mock for each Logger
  • all call to Logger method are delegated to instance of SimpleLogger, so you can create standard simplelogger.properties
  • light transitive dependencies - only slf4j-api and mockito-core

First we should add slf4j-mock binding as dependency to our project, we must remember that we can have only one slf4j binding on classpath.

<dependency>
    <groupId>org.simplify4u</groupId>
    <artifactId>slf4j-mock</artifactId>
    <version>1.0.0<version>
    <scope>test</scope>
</dependency>

Now we have class which does some logging action

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Example {

    private static final Logger LOGGER = LoggerFactory.getLogger(Example.class);

    public void methodWithLogDebug(String format, String args) {

        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug(format, args);
        }
    }

    public void methodWithLogWarn(String message) {
        LOGGER.warn(message);
        LOGGER.warn(message);
    }

    public void logError10() {
        for (int i = 0; i < 10; i++) {
            LOGGER.error("error: {}", i);
        }
    }
}

And finally we write test for it

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;

import org.junit.Before;
import org.junit.Test;
import org.simplify4u.sjf4jmock.LoggerMock;
import org.slf4j.Logger;

public class ExampleTest {

    private static final String INFO_TEST_MESSAGE = "info log test message";
    private static final String WARN_TEST_MESSAGE = "warn log test message";
    private static final String DEBUG_TEST_MESSAGE = "debug log test message";
    private static final String DEBUG_TEST_FORMAT = "Debug: {}";

    private Example sut;

    @Before
    public void setup() {
        LoggerMock.clearInvocations();
        sut = new Example();
    }


    @Test
    public void debugShouldNotBeLogged() {

        // given
        Logger logger = LoggerMock.getLoggerMock(Example.class);
        when(logger.isDebugEnabled()).thenReturn(false);

        // when
        sut.methodWithLogDebug(DEBUG_TEST_FORMAT, DEBUG_TEST_MESSAGE);

        // then
        verify(logger).isDebugEnabled();
        verifyNoMoreInteractions(logger);
    }

    @Test
    public void debugShouldBeLogged() {

        // given
        Logger logger = LoggerMock.getLoggerMock(Example.class);
        when(logger.isDebugEnabled()).thenReturn(true);

        // when
        sut.methodWithLogDebug(DEBUG_TEST_FORMAT, DEBUG_TEST_MESSAGE);

        // then
        verify(logger).isDebugEnabled();
        verify(logger).debug(DEBUG_TEST_FORMAT, DEBUG_TEST_MESSAGE);
        verifyNoMoreInteractions(logger);
    }

    @Test
    public void warnShouldBeLoggedTwice() {

        // when
        sut.methodWithLogWarn(WARN_TEST_MESSAGE);

        // then
        Logger logger = LoggerMock.getLoggerMock(Example.class.getName());
        verify(logger, times(2)).warn(WARN_TEST_MESSAGE);
        verifyNoMoreInteractions(logger);
    }

    @Test
    public void errorShouldBeLogged10Times() {

        // when
        sut.logError10();

        // then
        Logger logger = LoggerMock.getLoggerMock(Example.class.getName());
        verify(logger, times(10)).error(anyString(), any(Object.class));
        verifyNoMoreInteractions(logger);
    }
}

As we see thanks mocking slf4j logger we can prepare test for many scenario which we want.

In case of new requirement, bugs or other feedback we invite to github project slf4-mock https://github.com/s4u/slf4j-mock


Tags: slf4j mock testing