Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Junit testing log statements

I have a java 8 app with a class foo like this:

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

public class Foo {
    private final Logger log = LoggerFactory.getLogger(Foo.class);

    public String something() {
        log.info("doing foo test");
        return "test";
    }
}

Which I am writing a JUnit (Junit 4.11) test case for like this:

public class FooTest {
    private Foo foo;

    @Before
    public void setUp() throws Exception {
        foo = new Foo();
    }

    @Test
    public void testSomething() {
        String result = foo.something();
        assertEquals(result,"test");
    }
}

My objective is to write a test case that tests the something method for it's return value AND the logging statement to make sure something is being logged. I've spent hours scouring the web to figure out how to setup the junit to test the logging statement. I've tried this, this, this and this method to no avail.

I don't know if it's something I'm doing wrong or what. But here's my code based on the last example:

public class FooTest {
    private Foo foo;
    @Mock private Appender appender;
    @Captor private ArgumentCaptor captor;

    @Before
    public void setUp() throws Exception {
        foo = new Foo();
        MockitoAnnotations.initMocks(this);
        Logger.getRootLogger().addAppender(appender);
    }

    @After
    public void tearDown() throws Exception {
        Logger.getRootLogger().removeAllAppenders();
    }

    @Test
    public void testSomething() {
        String result = foo.something();
        assertEquals(result,"test");
        verify(appender).doAppend(((LoggingEvent) captor.capture()));
        LoggingEvent loggingEvent = (LoggingEvent) captor.getValue();
        assertEquals(loggingEvent.getRenderedMessage(), "doing foo test");
    }
}

But when I run this I get the following error:

Wanted but not invoked:
appender.doAppend(<Capturing argument>);
-> at <package>.testSomething(FooTest.java:22)
Actually, there were zero interactions with this mock.

Is there an easier way to accomplish what I want? If this is the best way then what am I doing wrong?

like image 562
Richard Avatar asked Aug 09 '16 22:08

Richard


People also ask

How do you do logs in Java?

The process of creating a new Logger in Java is quite simple. You have to use Logger. getLogger() method. The getLogger() method identifies the name of the Logger and takes string as a parameter.


1 Answers

Sure!

  • Create your own custom in-memory Singleton Appender class
  • Modify the testing logger configuration to log to this appender in addition to all other logging you will do
  • clear() it during each test @Begin
  • assert-test it normally before the test finishes.

In fact, SLF4J already has an implementation of this which you can look at.

like image 53
Tassos Bassoukos Avatar answered Oct 18 '22 03:10

Tassos Bassoukos