简体   繁体   中英

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?

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.

About how to set up the JUnit to test the logging statement, I think I found the answer. Here is the code.

package com.example.demo;

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;
import lombok.Getter;
import org.junit.Test;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;


public class FooTest {

    @Test
    public void somethingTest() {
        Appender appender = new Appender();
        Logger logger = (Logger) LoggerFactory.getLogger(Foo.class);
        logger.addAppender(appender);
        appender.start();

        (new Foo()).something();

        assertEquals(1, appender.getEvents().size());
        assertEquals("doing foo test", appender.getEvents().get(0).getMessage());

    }

}
@Getter
class Appender extends AppenderBase<ILoggingEvent> {
    private List<ILoggingEvent> events = new ArrayList<>();

    @Override
    protected void append(ILoggingEvent iLoggingEvent) {
        events.add(iLoggingEvent);
    }
}

private Logger baseLoggerMock = (Logger) LoggerFactory.getLogger(MyService.class); private ListAppender baseListAppender = new ListAppender<>(); private List logsList = baseListAppender.list;

@BeforeEach
void setUp() {
    baseListAppender.start();
    baseLoggerMock.addAppender(baseListAppender);
}

@Test void shouldCallLoggerAndLogMessages() {

    assertEquals(
            "My Message",
            logsList.get(0).getFormattedMessage());
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM