Search code examples
javajunit4log4j2

Log4j2: Junit test cases are failing


I am writing JUnit test cases for log4j2 logger as follows

import static org.junit.Assert.assertTrue;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class SampleLoggerTest {
    private ByteArrayOutputStream outContent = new ByteArrayOutputStream();
    private Logger logger = null;
    private PrintStream sysOut = System.out;

    @Before
    public void setUpStreams() {
        System.setOut(new PrintStream(outContent));
        logger = LogManager.getLogger(SampleLoggerTest.class);
    }

    @After
    public void restoreStreams() {
        System.setOut(sysOut);
    }

    @Test
    public void error() {
        logger.error("OnLogger");
        assertTrue(outContent.toString().contains("error"));
    }

    @Test
    public void debug() {
        logger.debug("OnLogger");
        assertTrue(outContent.toString().contains("debug"));
    }

    @Test
    public void fatal() {
        logger.fatal("OnLogger");
        assertTrue(outContent.toString().contains("fatal"));
    }

    @Test
    public void info() {
        logger.info("OnLogger");
        assertTrue(outContent.toString().contains("info"));
    }

    @Test
    public void warn() {
        logger.warn("OnLogger");
        assertTrue(outContent.toString().contains("warn"));
    }

    @Test
    public void trace() {
        logger.trace("OnLogger");
        assertTrue(outContent.toString().contains("trace"));
    }
}

But only one test case is successful, that is, info() I found outContent is containing log statement for first test case which is info() and it is successful but for rest of the test cases outContent is blank.

I tried flushing/closing stream in restoreStreams() but not worked, I also checked console output, there everything is getting printed, as I kept logging level to trace

Can anybody help me to find what I am missing in this?

Following is the console output:

2018-04-19 11:53:31.636 INFO [main] [com.logger.SampleLoggerTest] [info] [com.logger.SampleLoggerTest.info(SampleLoggerTest.java:60)] - logger
2018-04-19 11:54:39.197 WARN [main] [com.logger.SampleLoggerTest] [warn] [com.logger.SampleLoggerTest.warn(SampleLoggerTest.java:69)] - logger
2018-04-19 11:54:41.790 DEBUG [main] [com.logger.SampleLoggerTest] [debug] [com.logger.SampleLoggerTest.debug(SampleLoggerTest.java:42)] - logger
2018-04-19 11:54:43.966 ERROR [main] [com.logger.SampleLoggerTest] [error] [com.logger.SampleLoggerTest.error(SampleLoggerTest.java:33)] - logger
2018-04-19 11:54:46.254 FATAL [main] [com.logger.SampleLoggerTest] [fatal] [com.logger.SampleLoggerTest.fatal(SampleLoggerTest.java:51)] - logger
2018-04-19 11:54:48.309 TRACE [main] [com.logger.SampleLoggerTest] [trace] [com.logger.SampleLoggerTest.trace(SampleLoggerTest.java:78)] - logger

Solution

  • log4j gets initialized only once, so the @Before and @After-Methods dont impact Log4J2.

    Another Problem in your SampleLoggerTest is the ByteArrayOutputStream, it's initialized once, when an Instance of the SampleLoggerTest-Class is created and might be closed, when the @Before-Method is called the second time.

    The following Code works for me:

    import java.io.ByteArrayOutputStream;
    import java.io.PrintStream;
    
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.junit.Assert;
    import org.junit.BeforeClass;
    import org.junit.Test;
    
    public class SampleLoggerTest {
        private static ByteArrayOutputStream outContent;
        private static Logger logger = null;
        private static PrintStream printStream;
    
        @BeforeClass
        public static void init() {
            SampleLoggerTest.outContent = new ByteArrayOutputStream();
            SampleLoggerTest.printStream = new PrintStream(SampleLoggerTest.outContent);
            System.setOut(SampleLoggerTest.printStream);
            SampleLoggerTest.logger = LogManager.getLogger(SampleLoggerTest.class);
        }
    
        @Test
        public void debug() {
            SampleLoggerTest.logger.debug("OnLogger");
            Assert.assertTrue(SampleLoggerTest.outContent.toString().contains("DEBUG"));
        }
    
        @Test
        public void error() {
            SampleLoggerTest.logger.error("OnLogger");
            Assert.assertTrue(SampleLoggerTest.outContent.toString().contains("ERROR"));
        }
    
        @Test
        public void fatal() {
            SampleLoggerTest.logger.fatal("OnLogger");
            Assert.assertTrue(SampleLoggerTest.outContent.toString().contains("FATAL"));
        }
    
        @Test
        public void info() {
            SampleLoggerTest.logger.info("OnLogger");
            Assert.assertTrue(SampleLoggerTest.outContent.toString().contains("INFO"));
        }
    
        @Test
        public void trace() {
            SampleLoggerTest.logger.trace("OnLogger");
            Assert.assertTrue(SampleLoggerTest.outContent.toString().contains("TRACE"));
        }
    
        @Test
        public void warn() {
            SampleLoggerTest.logger.warn("OnLogger");
            Assert.assertTrue(SampleLoggerTest.outContent.toString().contains("WARN"));
        }
    }
    

    After executing the last @Test-Method, in my case its trace,the ByteArrayOutputStream looks like this:

    10:44:32.848 [main] INFO  de.crm.tools.SampleLoggerTest - OnLogger
    10:44:32.848 [main] WARN  de.crm.tools.SampleLoggerTest - OnLogger
    10:44:47.601 [main] DEBUG de.crm.tools.SampleLoggerTest - OnLogger
    10:44:47.601 [main] ERROR de.crm.tools.SampleLoggerTest - OnLogger
    10:44:47.601 [main] FATAL de.crm.tools.SampleLoggerTest - OnLogger
    10:44:47.601 [main] TRACE de.crm.tools.SampleLoggerTest - OnLogger