Last active
March 9, 2022 08:16
-
-
Save bloodredsun/a041de13e57bf3c6c040 to your computer and use it in GitHub Desktop.
Unit testing logback based logging statements
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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")); | |
} | |
} |
Thank you!
I had the same code but all my logger imports were from log4j package due to which I was getting error while doing Mockito.verify()
Error : Wanted but not invoked:
mockAppender.doAppend();
Actually, there were zero interactions with this mock.
After looking at your code, I changed all my imports to logback and it worked like a charm!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
So handy! Thanks!