Как установить уровень журнала DEBUG во время тестов Junit?

Я использую 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>

Как мне достичь этого результата?

РЕДАКТИРОВАТЬ: Я думаю, что я не был достаточно ясен. Этот вопрос не о настройке правильного уровня журнала... Речь идет об установке уровня журнала DEBUG при запуске тестов Junit и настройке уровня журнала INFO в любой другой ситуации. Я хочу автоматизировать это.

6 ответов

Решение

Вам не нужно предоставлять JVM другую реализацию журнала.

Лог-код ищет log4j.properties файл с использованием пути к классам. Так что все, что вам нужно сделать, это убедиться, что ваш тест log4j.properties Файл находится в месте, которое он найдет до выпуска файла.

Я использую Maven, который выкладывает файлы в каталоги, чтобы сделать это проще. Мой релиз log4j.properties идет в каталог src/main/resources, Моя тестовая версия идет в src/test/resources, Путь сборки Eclipse (classpath) настроен для поиска src/test/resources до src/main/resources, так что ваши юнит-тесты используют тестовый файл. Инструкции по сборке JAR (или WAR) используют файлы из src/main/resources,

Изменение уровня журнала ниже 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);
}

Вы можете использовать org.apache.logging.log4j.core.config.Configurator который имеет setAllLevels метод.

В своем тесте вы можете использовать его в @Before метод:

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

ПРИМЕЧАНИЕ: протестировано с привязкой org.slf4j:slf4j-log4j12:1.7.26

Возможно , это не совсем связано с вопросом в первую очередь, однако запрос Google приведет большинство разработчиков к этой теме, когда они будут искать способ

как изменить уровень журнала для некоторых методов тестирования 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();
}

Обычно LEVEL.FINEST должен это делать... но взгляните на http://saltnlight5.blogspot.mx/2013/08/how-to-configure-slf4j-with-different.html чтобы увидеть рассмотрение реализаций каркасов ведения журналов.

Как уже упоминалось, система logback использует src/test/resources/logback-test.xmlфайл для настройки уровней журнала модульного тестирования. Вот пример файла:

      <?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
    <appender name="ConsoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
        </encoder>
    </appender>

    <root>
        <level value="DEBUG" />
        <appender-ref ref="ConsoleAppender" />
    </root>

    <logger name="com.example.report" level="TRACE" additivity="false">
        <appender-ref ref="ConsoleAppender" />
    </logger>

</Configuration>

В этом примере корневой (по умолчанию) уровень журнала установлен на DEBUG. Классы в com.example.reportпакет регистрирует свои сообщения в TRACEуровня и ниже.

Другие вопросы по тегам