log4j 如何在Junit测试期间将日志级别设置为DEBUG?

mwkjh3gx  于 2022-11-06  发布在  其他
关注(0)|答案(5)|浏览(357)

我使用的是带有LOG4J的SLF 4J,配置通常在log4j.properties中,它将日志级别设置为INFO。
但是,在测试期间,我希望将日志设置为DEBUG。
我看不出有什么方法可以自动完成这个过程,也不知道有没有像log4j.tests.properties这样只在测试期间加载的东西。
因此,我尝试在测试设置(@BeforeClass)中以编程方式执行此操作:

LogManager.getRootLogger().setLevel(Level.ALL);

没有成功...
我正在使用这些版本:

<dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.5</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.5</version>
    </dependency>

我怎样才能达到这个结果呢?

**编辑:**我想我还不够清楚。这个问题不是关于设置正确的日志级别...而是关于在运行Junit测试时设置DEBUG日志级别,以及在任何其他情况下设置INFO日志级别。我想自动化这个问题。

2o7dmzc5

2o7dmzc51#

您不需要为JVM提供不同的日志实现。
日志记录代码使用类路径搜索log4j.properties文件,因此您所需要做的就是确保您的测试log4j.properties文件位于发布文件之前的位置。
我使用了Maven,它将文件放在目录中,这样做会更容易。我的发布版本log4j.properties放在src/main/resources目录中。我的测试版本放在src/test/resources目录中。Eclipse构建路径(classpath)被设置为在src/main/resources之前搜索src/test/resources,因此您的单元测试使用测试文件。JAR(或WAR)构建指令使用来自src/main/resources的文件。

lymgl2op

lymgl2op2#

以下ROOT日志级别更改将对junit起作用,以将日志记录设置为所需级别。

import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;

@Before
public void setUp() {
    final Logger logger = (Logger)LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
    logger.setLevel(Level.ALL);
}
qkf9rpyu

qkf9rpyu3#

您可以使用具有setAllLevels方法的org.apache.logging.log4j.core.config.Configurator
在您的测试中,您可以在@Before方法中使用它:

@Before
  public void changeLogLevel() {
    Configurator.setAllLevels("", Level.ALL);
  }

注:使用绑定org.slf4j:slf4j-log4j12:1.7.26进行测试

7tofc5zh

7tofc5zh4#

也许一开始并不完全与这个问题相关,但是,当大多数开发人员在搜索

如何更改某些junit测试方法的日志级别。

方法是使用一个定制的junit MethodRule来访问记录器并重新配置每个包的日志级别。
使用下面的类,你可以做到这一点。它设置包和类的日志级别,如测试方法注解中定义的那样,当测试完成时,将日志程序设置回它们的初始状态。我们假设默认的日志级别当前设置为INFO。

@Test
@LogLevel(packageToLevel = { "my.java.package=DEBUG", "my.other.java.package.ClassNeedsTracing=TRACE" })
public void allLogsOfThatPackageAreInDebugNow() {
   ...
}

@Test
@LogLevel(packageToLevel = { "my.java.package=TRACE", "my.java.package.ClassNoTracing=TRACE" })
public void allLogsOfThatPackageAreInTraceNowExceptOneClass() {
   ...
}

为了实现这一点,你需要在你的测试类中指定测试规则:

@Rule
LogLevelRule logLevelRule = new LogLevelRule();

所需的类在下面找到:

import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;

/**
 * a Junit Rule that check for LogLevel annotation on methods and activates the configured log level per package. After
 * the test was executed, restores the previous log level.
 */
public class LogLevelRule implements MethodRule {

    @Override
    public Statement apply(Statement base, FrameworkMethod method, Object target) {

        return new Statement() {
            @Override
            public void evaluate() throws Throwable {

                // activate log level desired, remember what they were
                Map<String, Level> existingPackageLogLevel = new HashMap<>();
                LogLevel logLevelAnnotation = method.getAnnotation(LogLevel.class);
                if (logLevelAnnotation != null) {
                    activate(logLevelAnnotation.packageToLevel(), existingPackageLogLevel);
                }

                // run the test
                Throwable testFailure = evaluateSafely(base);

                // revert the log level back to what it was
                if (!existingPackageLogLevel.isEmpty()) {
                    deactivate(existingPackageLogLevel);
                }

                if (testFailure != null) {
                    throw testFailure;
                }
            }

            /**
             * execute the test safely so that if it fails, we can still revert the log level
             */
            private Throwable evaluateSafely(Statement base) {
                try {
                    base.evaluate();
                    return null;
                } catch (Throwable throwable) {
                    return throwable;
                }
            }
        };
    }

    /**
     * activates the log level per package and remember the current setup
     *
     * @param packageToLevel
     *            the configuration of the annotation
     * @param existingPackageLogLevel
     *            where to store the current information
     */
    protected void activate(String[] packageToLevel, Map<String, Level> existingPackageLogLevel) {
        for (String pkgToLevel : packageToLevel) {
            String[] split = pkgToLevel.split("=");
            String pkg = split[0];
            String levelString = split[1];
            Logger logger = LogManager.getLogger(pkg);
            Level level = logger.getLevel();
            existingPackageLogLevel.put(pkg, level);
            logger.setLevel(Level.toLevel(levelString));
        }
    }

    /**
     * resets the log level of the changes packages back to what it was before
     *
     * @param existingPackageLogLevel
     */
    protected void deactivate(Map<String, Level> existingPackageLogLevel) {
        for (Map.Entry<String, Level> e : existingPackageLogLevel.entrySet()) {
            LogManager.getLogger(e.getKey()).setLevel(e.getValue());
        }
    }

}

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * marks a method to use a different log level for the execution phase
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface LogLevel {
    String[] packageToLevel();
}
nx7onnlm

nx7onnlm5#

通常LEVEL.FINEST应该可以做到...但是看看http://saltnlight5.blogspot.mx/2013/08/how-to-configure-slf4j-with-different.html,看看日志框架的实现是否考虑了创建。

相关问题