首页 > 解决方案 > Spring Boot - @Slf4j Logging Behavior differs in Test and in real Application

问题描述

I have a sample class like this,

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class TestLogging {

    public void printLogLevel(){

        if(log.isErrorEnabled()){
            log.error("Error Enabled");
        }

        if(log.isTraceEnabled()){
            log.trace("Trace Enabled");
        }

        if(log.isInfoEnabled()){
            log.info("Info Enabled");
        }

        if(log.isDebugEnabled()){
            log.debug("DEBUG enabled");
        }
    }
}

I have written a test case like this,

import org.junit.Test;

public class TestLoggingTest {
    TestLogging testLogging = new TestLogging();

    @Test
    public void testLoggingLevel(){
        testLogging.printLogLevel();
    }
}

When I run this test the below items gets printed to console.

19:48:54.661 [main] ERROR com.tejas.springlogging.TestLogging - Error Enabled
19:48:54.665 [main] INFO com.tejas.springlogging.TestLogging - Info Enabled
19:48:54.666 [main] DEBUG com.tejas.springlogging.TestLogging - DEBUG enabled

But when I run the printLogLevel() from application like this,

@SpringBootApplication
@Slf4j
public class SpringLoggingApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringLoggingApplication.class, args);

        TestLogging testLogging = new TestLogging();
        testLogging.printLogLevel();
    }

}

The below lines gets printed to console.

2021-10-12 20:05:27.183 ERROR 8924 --- [           main] com.tejas.springlogging.TestLogging      : Error Enabled
2021-10-12 20:05:27.183  INFO 8924 --- [           main] com.tejas.springlogging.TestLogging      : Info Enabled

Below are the dependencies I have used for this testing.

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>optional</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.hamcrest</groupId>
                    <artifactId>hamcrest-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

and this is the parent pom version.

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

Now the question is, why there is a difference when I call the printLogLevel() method from test and from application. The debug level gets printed only from test. May I know why?

EDIT: Adding @SpringBootTest fixes this issue as suggest by @narendra, but it works only with junit5. I want the fix in junit4

标签: javaspring-bootloggingslf4j

解决方案


In application, it is using Slf4j in Spring application context, and because of this it uses Spring's default pattern for logging. The default log level is INFO.

See Log Format for Spring.

This pattern is different from SLF4j default pattern.

With no configuration, the default output includes the relative time in milliseconds, thread name, the level, logger name, and the message followed by the line separator for the host. In log4j terms it amounts to the "%r [%t] %level %logger - %m%n" pattern. Sample output follows.

 176 [main] INFO examples.Sort - Populating an array of 2 elements in reverse order.  
 225 [main] INFO examples.SortAlgo - Entered the sort method.
 304 [main] INFO examples.SortAlgo - Dump of integer array:
 317 [main] INFO examples.SortAlgo - Element [0] = 0

The default log level would depend on initialization of logger for plain SLF4j logging.


Solution: You can add SpringBootTest to test class for uniform logging pattern.


推荐阅读