Is it possible to somehow intercept the logging (SLF4J + logback) and get an InputStream
(or something else that is readable) via a JUnit test case...?
SLF4J supports popular logging frameworks, namely log4j, java. util. logging, Simple logging and NOP. The logback project supports SLF4J natively.
@StefanoL: If a logger is defined with private static final Logger LOGGER = Logger. getLogger(someString); , you can still access it from unit tests with Logger. getLogger(someString); , modify it and add handlers (as in the accepted answer).
how to change the log level for certain junit test methods. The way to go is to use a custom junit MethodRule that accesses the loggers and re-configures the log level per package. With below classes, you can achieve this.
The SLF4J or the Simple Logging Facade for Java is an abstraction layer for various Java logging frameworks, like Log4j 2 or Logback.
The Slf4j API doesn't provide such a way but Logback provides a simple solution.
You can use ListAppender
: a whitebox logback appender where log entries are added in a public List
field that we could use to make our assertions.
Here is a simple example.
Foo class :
import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Foo { static final Logger LOGGER = LoggerFactory.getLogger(Foo .class); public void doThat() { logger.info("start"); //... logger.info("finish"); } }
FooTest class :
import org.slf4j.LoggerFactory; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.read.ListAppender; public class FooTest { @Test void doThat() throws Exception { // get Logback Logger Logger fooLogger = (Logger) LoggerFactory.getLogger(Foo.class); // create and start a ListAppender ListAppender<ILoggingEvent> listAppender = new ListAppender<>(); listAppender.start(); // add the appender to the logger fooLogger.addAppender(listAppender); // call method under test Foo foo = new Foo(); foo.doThat(); // JUnit assertions List<ILoggingEvent> logsList = listAppender.list; assertEquals("start", logsList.get(0) .getMessage()); assertEquals(Level.INFO, logsList.get(0) .getLevel()); assertEquals("finish", logsList.get(1) .getMessage()); assertEquals(Level.INFO, logsList.get(1) .getLevel()); } }
You can also use Matcher/assertion libraries as AssertJ or Hamcrest.
With AssertJ it would be :
import org.assertj.core.api.Assertions; Assertions.assertThat(listAppender.list) .extracting(ILoggingEvent::getFormattedMessage, ILoggingEvent::getLevel) .containsExactly(Tuple.tuple("start", Level.INFO), Tuple.tuple("finish", Level.INFO));
You can create a custom appender
public class TestAppender extends AppenderBase<LoggingEvent> { static List<LoggingEvent> events = new ArrayList<>(); @Override protected void append(LoggingEvent e) { events.add(e); } }
and configure logback-test.xml to use it. Now we can check logging events from our test:
@Test public void test() { ... Assert.assertEquals(1, TestAppender.events.size()); ... }
NOTE: Use ILoggingEvent
if you do not get any output - see the comment section for the reasoning.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With