What is the strategy to mock static loggers in java service using mockito

cpandey05 picture cpandey05 · Oct 17, 2013 · Viewed 8.5k times · Source

I see that loggers have been mocked with help of Powermock or some sort of overridden constructor which takes logger.

Being logger used all over the code, is not their a simple way using just mockito? Some way to ignore the call or mock it - I do not want to validate any message, just want to avoid the Null Pointer exception

I am new to mocking frameworks so I am wondering rather use Jmockit instead of mixing and matching two libraries -The only reason to avoid jomockit so far -its just too power full and can easily be misused!

Answer

Dennis picture Dennis · Oct 17, 2013

I use verification of logs in cases where I think that it is very important to log at a certain level. This is how I do it using Mockito:

Utility Class

public final class LoggingTestUtil {

    private LoggingTestUtil() {
    }

    public static void setupLoggingMock(Logger logger, Appender<ILoggingEvent> appender) {
        logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
        when(appender.getName()).thenReturn("MOCK");
        logger.addAppender(appender);
    }

    public static void verifyLogAppended(Appender<ILoggingEvent> appender, final String loggedString) {
        verify(appender).doAppend(argThat(new ArgumentMatcher<LoggingEvent>() {
            @Override
            public boolean matches(final Object argument) {
                return ((LoggingEvent) argument).getMessage().contains(loggedString);
            }
        }));
    }

    public static void verifyLogAppendedAtLevel(Appender<ILoggingEvent> appender, final Level level) {
        verify(appender).doAppend(argThat(new ArgumentMatcher<LoggingEvent>() {
            @Override
            public boolean matches(final Object argument) {
                return ((LoggingEvent) argument).getLevel().equals(level);
            }
        }));
    }

    public static void verifyLogAppendedAtLevel(Appender<ILoggingEvent> appender, final Level level, final String loggedString) {
        verify(appender).doAppend(argThat(new ArgumentMatcher<LoggingEvent>() {
            @Override
            public boolean matches(final Object argument) {
                LoggingEvent event = (LoggingEvent) argument;
                return event.getLevel().equals(level) && event.getMessage().contains(loggedString);
            }
        }));
    }
}

In Test Class

private static Logger root;
@Mock
private static Appender<ILoggingEvent> mockAppender; // used to test that logging occurs

    @Test
    public final void testSomething(){
        LoggingTestUtil.setupLoggingMocks(root, mockAppender);
        underTest.doSomethingBad();
        LoggingTestUtil.verifyLogAppendedAtLevel(mockAppender, Level.ERROR, "bad thing");
    }