Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Unit testing logback based logging statements
package com.brs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Simple class that we use to trigger a log statement.
*/
public class ExampleThatLogs {
private static final Logger LOG = LoggerFactory.getLogger(ExampleThatLogs.class);
public String concat(String a, String b) {
LOG.info("String a:" + a + ", String b:" + b);
return a+b;
}
}
package com.brs;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.Appender;
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 org.slf4j.LoggerFactory;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.verify;
/**
* Our Test class shows how we can hook into logback with mockito to see the
* logging activity
*/
@RunWith(MockitoJUnitRunner.class)
public class ExampleThatLogsTest {
@Mock
private Appender mockAppender;
//Captor is genericised with ch.qos.logback.classic.spi.LoggingEvent
@Captor
private ArgumentCaptor<LoggingEvent> captorLoggingEvent;
//I've cheated a little here and added the mockAppender to the root logger
//It's not quite necessary but it also shows you how it can be done
@Before
public void setup() {
final Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
logger.addAppender(mockAppender);
}
//Always have this teardown otherwise we can stuff up our expectations. Besides, it's
//good coding practise
@After
public void teardown() {
final Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
logger.detachAppender(mockAppender);
}
@Test
public void shouldConcatAndLog() {
//given
ExampleThatLogs example = new ExampleThatLogs();
//when
final String result = example.concat("foo", "bar");
//then
assertEquals("foobar", result);
//Now verify our logging interactions
verify(mockAppender).doAppend(captorLoggingEvent.capture());
//Having a genricised captor means we don't need to cast
final LoggingEvent loggingEvent = captorLoggingEvent.getValue();
//Check log level is correct
assertThat(loggingEvent.getLevel(), is(Level.INFO));
//Check the message being logged is correct
assertThat(loggingEvent.getFormattedMessage(),
is("String a:foo, String b:bar"));
}
}

Very helpful

Could you show me the pom please? I'm having a problem and probably because of the packages versions.
I'm getting:

Wanted but not invoked:
mockAppender.doAppend();
-> at com.br.ExampleThatLogsTest.shouldConcatAndLog(ExampleThatLogsTest.java:61)
Actually, there were zero interactions with this mock.

birqan commented May 24, 2017

A big and fat THANK YOU for your share. Thumbs up!

Very Helpful! Thank You!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment