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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38778026/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 20:38:44  来源:igfitidea点击:

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

javajunitlog4jslf4j

提问by PedroD

I am using SLF4J with LOG4J, and the configurations are usually in the log4j.properties, and it sets the log level to INFO.

我将 SLF4J 与 LOG4J 一起使用,配置通常在 .log 中,并将log4j.properties日志级别设置为 INFO。

However during the tests I would like to set the logs to DEBUG.

但是在测试期间,我想将日志设置为 DEBUG。

I can't see a way to automate this, neither to have something like log4j.tests.propertiesthat would be loaded only during tests.

我看不到自动化的方法,也没有log4j.tests.properties只在测试期间加载类似的东西。

So I've tried doing this programmatically in the test setup (the @BeforeClass):

所以我尝试在测试设置(@BeforeClass)中以编程方式执行此操作:

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

With no success...

没有成功...

I am using these versions:

我正在使用这些版本:

    <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>

How can I achieve this result?

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

EDIT:I think I wasn't clear enough. This question is not about setting the correct log level... It is about setting the DEBUG log level when running Junit tests, and setting INFO log level in any other situation. I want to automate this.

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

采纳答案by PedroD

You do not need to give the JVM a different log implementation.

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

The logging code searches for the log4j.propertiesfile using the classpath. So all you need to do is ensure that your test log4j.propertiesfile is in a location that it will find before the release file.

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

I use Maven, which lays out files in directories to make that easy. My release log4j.propertiesgoes in the directory src/main/resources. My test version goes in src/test/resources. The Eclipse build path (classpath) is set up to search src/test/resourcesbefore src/main/resources, so your unit tests use the test file. The JAR (or WAR) build instructions use the files from src/main/resources.

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

回答by Carlos de Luna Saenz

Usually LEVEL.FINEST should do it... but take a look to http://saltnlight5.blogspot.mx/2013/08/how-to-configure-slf4j-with-different.htmlto see logging frameworks implementations considereation.

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

回答by Nicolas Massart

You can use the org.apache.logging.log4j.core.config.Configuratorwhich has a setAllLevelsmethod.

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

In your test you can use it in a @Beforemethod:

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

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

NOTE: tested with binding org.slf4j:slf4j-log4j12:1.7.26

注意:通过绑定测试org.slf4j:slf4j-log4j12:1.7.26

回答by Achu22

Below ROOT log level change will work for junit to set logging to desired level.

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

回答by Remo Liechti

maybe not entirely related to the question in the first place, however a google query will lead most developers to this topic when they search for a way on

一开始可能与问题并不完全相关,但是当大多数开发人员搜索方法时,谷歌查询会将他们引向这个主题

how to change the log level for certain junit test methods.

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

The way to go is to use a custom junit MethodRule that accesses the loggers and re-configures the log level per package.

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

With below classes, you can achieve this. It sets the log level for packages and classes as defines in the annotation of a test method and when the test has finished, sets the loggers back to their initial state. We assume the default log level is set to INFO currently.

通过以下课程,您可以实现这一目标。它按照测试方法的注释中的定义设置包和类的日志级别,当测试完成时,将记录器设置回它们的初始状态。我们假设默认日志级别当前设置为 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() {
   ...
}

To achieve this, you need so specify the test rule in your test class:

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

@Rule
LogLevelRule logLevelRule = new LogLevelRule();

Classes needed found below:

需要的课程如下:

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