Is there any simple pattern of slf4j usage in unit tests?

Viewed 31340

I'm using JUnit4 and Hibernate3 in my project. Hibernate depends on Slf4j and thus my project includes this library as well. Now I'd like to use Slf4j in unit tests in order to log supplementary testing information. Could you please provide a short example of how my unit test should look like in order to log just one line of text? Preferably without code duplication in multiple tests.

9 Answers

I didn't want to have to setup a xml file and I didn't want to use System.out.println. Mostly I needed this for unit tests.

You can set the test logger:

<!-- Use SimpleLogger as the slf4j implementation in test -->
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-simple</artifactId>
  <version>1.7.12</version>
  <scope>test</scope>
</dependency>

Before you create your Logger set this property: (ref: http://www.slf4j.org/api/org/slf4j/impl/SimpleLogger.html other properties available other than TRACE)

static {
    System.setProperty("org.slf4j.simpleLogger.defaultLogLevel","TRACE");
}

Create the logger:

private static final Logger LOGGER = LoggerFactory.getLogger(MyClass.class);


private void doSomeLogs(){
    LOGGER.trace("trace it"); 
}

If you (allow) for the injection of a logger, you can use.

testImplementation group: 'com.portingle', name: 'slf4jtesting', version: portingleSlf4jtestingVersion

https://github.com/portingle/slf4jtesting

You class looks like this:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;


public final class MyThing {

    private Logger logger;

    @Inject
    MyThingTest() {
        this(LoggerFactory
                .getLogger(MyThing.class));
    }

    public MyThing(final Logger lgr) {
        if (null == lgr) {
            throw new IllegalArgumentException("Logger is null");
        }
        this.logger = lgr;

    }

In your Unit Test code, you have have something like this:

@Test
public void myTest() {

    TestLogger unitTestLogger = this.getUnitTestLogger();


    MyThing testItem = new MyThing(unitTestLogger);
   testItem.doSomethingWithLogs();
}


private TestLogger getUnitTestLogger() {
    TestLoggerFactory loggerFactory = Settings.instance()
            .enableAll() // necessary as by default only ErrorLevel is enabled
            .buildLogging();

    TestLogger returnItem = loggerFactory.getLogger(MyThingTest.class.getName());
    assertNotNull(returnItem);
    return returnItem;
}



// render nicer errors
private void assertLoggerContains(TestLogger unitTestLogger, LogLevel logLev, String expected) throws Error {
    if (!unitTestLogger.contains(logLev, expected)) {
        throw new AssertionError("expected '" + expected + "' but got '" + unitTestLogger.lines() + "'");
    }
}

// render nicer errors
private void assertLoggerNotContains(TestLogger unitTestLogger, LogLevel logLev, String expected) throws Error {
    if (unitTestLogger.contains(logLev, expected)) {
        throw new AssertionError("expected absence of '" + expected + "' but got '" + unitTestLogger.lines() + "'");
    }
}
Related