How to test 2 log messages in JUnit and Mockito

Viewed 1269

I am very new to JUnit and Mockito. I am trying to write a test case using JUnit and Mockito to verify log messages. I have 2 log messages in my code.

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public int run(final String[] args) throws Exception {
    if (args.length != 2) {
      log.info("Usage: input-path output-path");
      log.info("Input and output path are required in the same sequence");
      System.exit(1);
    }
    final String inputPath = args[0];
    final String outputPath = args[1];
    //some code
    return 0;
}

The test case that I have written is

import org.apache.log4j.Appender;
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.log4j.spi.LoggingEvent;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.verify;

@RunWith(MockitoJUnitRunner.class)
public class testRun {

    @Mock
    private Appender mockAppender;

    @Before
    public void setup() {LogManager.getRootLogger().addAppender(mockAppender);}

    @After
    public void teardown() {LogManager.getRootLogger().removeAppender(mockAppender);}

    @Test
    public void testValidArguments() {
        //some code
 Logger.getLogger(TryTest.class).info("Usage: input-path output-path");
    Logger.getLogger(TryTest.class).info("Input and output path are required in the same sequence");
    ArgumentCaptor<LoggingEvent> argument = ArgumentCaptor.forClass(LoggingEvent.class);
    verify(appender,times(2)).doAppend(argument.capture());
    assertEquals(Level.INFO, argument.getValue().getLevel());
    assertEquals("Usage: input-path output-path", argument.getValue().getMessage());
    assertEquals("Input and output path are required in the same sequence", argument.getValue().getMessage());
     }
}

I have seen some solutions but they require to create another class which I do not want. Also while I execute the code it is taking the second value i.e., "Input and output path are required in the same sequence". The code executes fine if there is only one log message. I can put both the messages in one log.info if it cannot be solved. However, I do wish to know if there are any possible solution to this particular problem.

1 Answers

If you are using sl4j logger you could use ListAppender:

@Test
void test() {
    Logger logger = (Logger) LogFactory.getLogger(YourClass.class);

    ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
    listAppender.start();
    logger.addAppender(listAppender);

    YourClass yourClass = new YourClass();
    yourClass.callYourMethodWithLogs();

    List<ILoggingEvent> logsList = listAppender.list;
    //make assertions with logList
}
Related