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();
}
我正在使用 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();
}