Instantly share code, notes, and snippets.

Embed
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"));
}
}
@coryellenberger

This comment has been minimized.

coryellenberger commented Nov 5, 2015

Very helpful

@klassounski-daitan

This comment has been minimized.

klassounski-daitan commented Jun 30, 2016

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

This comment has been minimized.

birqan commented May 24, 2017

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

@abbas-mohamad

This comment has been minimized.

abbas-mohamad commented Dec 14, 2017

Very Helpful! Thank You!

@mallesh-np

This comment has been minimized.

mallesh-np commented Mar 5, 2018

Can you please share your logback.xml?

@nvlinh

This comment has been minimized.

nvlinh commented May 21, 2018

I use @RunWith(SpringJUnit4ClassRunner.class) for run it, but not work, please tell me the way use it with @RunWith(SpringJUnit4ClassRunner.class)

@manueldeveloper

This comment has been minimized.

manueldeveloper commented Sep 28, 2018

So handy! Thanks!

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