Junit测试时如何设置日志级别为DEBUG?

How to set the log level to DEBUG during Junit tests?

我正在使用 SLF4J 和 LOG4J,配置通常在 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 日志级别。我想将其自动化。

通常 LEVEL.FINEST 应该这样做...但请查看 http://saltnlight5.blogspot.mx/2013/08/how-to-configure-slf4j-with-different.html 以了解日志记录框架实现的考虑。

您不需要为 JVM 提供不同的日志实现。

日志代码使用类路径搜索 log4j.properties 文件。因此,您需要做的就是确保您的测试 log4j.properties 文件位于它可以在发布文件之前找到的位置。

我使用 Maven,它将文件布置在目录中以简化操作。我的发布 log4j.properties 在目录 src/main/resources 中。我的测试版本进入 src/test/resources。 Eclipse 构建路径(类路径)设置为在 src/main/resources 之前搜索 src/test/resources,因此您的单元测试使用测试文件。 JAR(或 WAR)构建指令使用来自 src/main/resources.

的文件

您可以使用具有 setAllLevels 方法的 org.apache.logging.log4j.core.config.Configurator

在您的测试中,您可以在 @Before 方法中使用它:

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

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

低于 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);
}

一开始可能与问题不完全相关,但是 google 查询会在大多数开发人员在

上搜索方法时将他们引导至该主题

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

方法是使用访问记录器并重新配置每个包的日志级别的自定义 junit MethodRule。

使用以下 classes,您可以实现此目的。它按照测试方法注释中的定义为包和 classes 设置日志级别,并在测试完成后将记录器设置回其初始状态。 我们假设当前默认日志级别设置为 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() {
   ...
}

为此,您需要在测试中指定测试规则 class:

@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();
}