Есть ли простой образец использования slf4j в модульных тестах?

Я использую JUnit4 и Hibernate3 в своем проекте. Hibernate зависит от Slf4j, и поэтому мой проект включает эту библиотеку. Теперь я хотел бы использовать Slf4j в модульных тестах, чтобы регистрировать дополнительную информацию тестирования. Не могли бы вы привести краткий пример того, как должен выглядеть мой unit test, чтобы записывать только одну строку текста? Предпочтительно без дублирования кода в нескольких тестах.

Ответы

Ответ 1

Мне также нравится использовать slf4j в моих тестах JUnit для моего класса DAO. Это помогает при создании нового теста или изменении старого. Обычно я оставляю свой старый вывод журнала на уровне отладки и делаю свои новые записи на информационном уровне, пока я все еще активно работаю над кодом в этом методе. Один из моих классов JUnit будет выглядеть примерно так:

package com.example.mydao;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// other imports not shown...

public class TestMyDAO extends TestCase {

    private static final Logger logger = 
        LoggerFactory.getLogger(TestMyDAO.class);


    public void testA() {
        logger.debug("Logging from testA() method");
    }

    public void testB() {
        logger.debug("Logging from testB() method");
    }

    public void testThatIAmWorkingOn() {
        logger.info("Logging from my new test method at INFO level");
    }

}

Я использую log4j как фактический поставщик протоколирования, поэтому файл конфигурации log4j.xml выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
    <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
    <appender name="consoleAppender" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %-5p  [%c{1}] %m %n" />
        </layout>
    </appender>

    <logger name="com.example.mydao" additivity="false">
        <level value="INFO" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="org.hibernate" additivity="false">
        <level value="WARN" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="org.hibernate.connection.DriverManagerConnectionProvider" additivity="false">
        <level value="INFO" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="org.hibernate.connection.C3P0ConnectionProvider" additivity="false">
        <level value="INFO" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="com.mchange" additivity="false">
        <level value="WARN" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="com.mchange.v2.resourcepool.BasicResourcePool" additivity="false">
        <level value="INFO" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource" additivity="false">
        <level value="INFO" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <logger name="com.mchange.v2.c3p0.C3P0Registry" additivity="false">
        <level value="INFO" />
        <appender-ref ref="consoleAppender"/>
    </logger>

    <root>
        <priority value ="WARN" />
        <appender-ref ref="consoleAppender"/>
    </root>

</log4j:configuration>

Это дает мне вывод информационного уровня моего класса JUnit, а также некоторые полезные материалы из среды исполнения Hibernate и других библиотек, используемых с Hibernate. Откорректируйте свой вкус.

Наконец, мне нужно убедиться, что все следующие библиотеки находятся в моем пути к классам при выполнении тестов JUnit:

  • slf4j-api-1.6.0.jar
  • slf4j-log4j12-1.6.0.jar
  • log4j-1.2.16.jar
  • log4j.xml (мой файл конфигурации, показанный выше)
  • Некоторая версия JUnit runtime JAR
  • Все JAR, обычно присутствующие при запуске вашего приложения в производстве

Это то, что я делаю при использовании log4j. Если вы используете другую реализацию каротажа, тогда отрегулируйте соответствующим образом. Не имеет значения, используете ли вы другую версию slf4j, если "API" и JAR реализации являются одной и той же версией (мои оба - 1.6.0).

Ответ 2

Почему вы хотите регистрировать события в unit test? Единичные тесты должны проходить с ошибкой и должны использовать структуру тестирования, чтобы указать это. Вы не хотите читать результаты, чтобы проверить, прошел тест или не прошел тест. И если это не удается, запуск его в IDE/отладчике - лучший способ его исправить.

Ответ 3

Другое решение - переключить реализацию журнала на простую реализацию только для тестов.

Итак, в вашем pom.xml

    <!-- Depend on slf4j API -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.12</version>
    </dependency>

    <!-- Use SimpleLogger as the slf4j implementation in test -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>1.7.12</version>
        <scope>test</scope>
    </dependency>

    <!-- Use log4j as the slf4j implementation during runtime (not test) -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.12</version>
        <scope>runtime</scope>
    </dependency>

SimpleLogger просто записывает все в stderr по умолчанию и не требует каких-либо файлов конфигурации

Ответ 4

Мы используем log4j в качестве нашего выходного регистратора;

private static Logger log = LoggerFactory.getLogger(MyClassHere.class);

slf4j должен найти и использовать log4j без проблем, если вы его правильно настроите. Чтобы сделать жизнь легкой, я бы использовал этот шаблон Eclipse, так как вы написали бы этот код справедливым битом:

private static Logger log = LoggerFactory.getLogger(${enclosing_type}.class);
${:import(org.slf4j.Logger,org.slf4j.LoggerFactory)}

для тестов я бы рекомендовал вам не подниматься выше уровня INFO и хранить большинство вещей в DEBUG. Если вы действительно хотите уловить множество ошибок разумно, я бы порекомендовал посмотреть на PositronLogger, который является приложением файла журнала, которое тихо будет забирать все на TRACE, но только сбрасывает его в файл, если он захватывает ERROR; вроде как время путешествия:)

http://github.com/andreaja/PositronLogger

Ответ 5

Slf4j - это Logging Facade, где вы можете решить реализацию во время выполнения. Slf4j - это просто API. Например, вы можете использовать log4j как базовую реализацию. Для этого вам нужно включить две зависимости в ваш pom.xml.

    <!-- Depend on slf4j API -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.12</version>
    </dependency>
    <!-- Use log4j as the slf4j implementation -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.12</version>
    </dependency>

Дело в том, что при выполнении модульных тестов в среде IDE или через mvn test может возникнуть раздражение при настройке конфигурации log4j. Особенно в том, что просто работает, не делая ничего. Log4j отказывается записывать что-либо по умолчанию, если у вас нет файла log4j.properties в пути к классам или не установлен -Dlog4j.configuration=file:///path/to/log4j.properties.

Одним из решений является установка кода unit test для программной настройки конфигурации log4j:

    @BeforeClass
    public static void beforeClass() {
        BasicConfigurator.resetConfiguration();
        BasicConfigurator.configure();
    }

Это просто работает, однако его нужно накладывать на каждый unit test, который является болью. .

Ответ 6

Добавление журнала при написании новых тестов полезно. В то же время, когда тесты выполняются в конвейере CI или CD, вы хотите, чтобы ведение журнала было отключено (или, по крайней мере, менее подробным). Иногда отказы преходящи, особенно в сквозном запуске, поэтому полезно иметь соответствующий вывод в консольном журнале задач CI. Эта статья описывает это очень хорошо - https://gualtierotesta.wordpress.com/2015/11/01/tutorial-logging-during-tests/

Ответ 7

Мне кажется, это плохой запах.

Вы всегда должны избегать ручного осмотра или проверки для unit test.

Unit test должен быть автоматизирован, человеческое вмешательство должно быть необходимо только в том случае, если ваши инструменты сборки говорят вам, что определенный тест не прошел, и причина сбоя должна быть предоставлена ​​с использованием всех этих методов проверки (например, assertEquals)