Как сделать так, чтобы вызовы log4j error () вызывали исключение в тестах jUnit? - PullRequest
7 голосов
/ 13 апреля 2011

У меня есть проект Java, тестируемый с помощью JUnit (смесь стилей Junit 3 и 4), где тестируемые классы могут регистрировать ошибку log4j.Я хотел бы сделать модульный тест неудачным, если такая ошибка будет зарегистрирована.

Существует ли общий способ настройки либо log4j, либо инфраструктуры модульного тестирования для выполнения любого вызова метода log4j error () в кодепри тестировании выдает исключение времени выполнения и, следовательно, не проходит тест?AOP может быть одним из способов, но меня интересуют и другие возможности.

Цель здесь - отсеять места в коде, где log4j error () используется неправильно.То есть, когда регистрируется ошибка, но не происходит исключений или обработки ошибок, либо это не действительно ошибка, либо она возникает и должна возникать.

например:

public class MyTest extends TestCase {
    public void testLogAnError() {
        // Want to make this fail
        new MyClass().logAnError();
    }
}

public class MyClass() {
    static Logger logger = Logger.getLogger("foo");

    public void logAnError() {
        // I'm logging an error, but not doing anything about it
        logger.error("Something bad, or is it?");
        // TODO throw an exception or don't log an error if there isn't one
    }
}

Обновить: Вот как выглядит решение, которое я использую в настоящее время.Он основан на ответе sbridges (добавлен в тестовый класс):

private static final Appender crashAndBurnAppender = new NullAppender () {
    public void doAppend(LoggingEvent event) {
         if(event.getLevel() == Level.ERROR) {
              throw new AssertionError("logged at error:" + event.getMessage());
         }
    }
};

Затем в setUp:

Logger.getRootLogger().addAppender(crashAndBurnAppender);

И tearDown:

Logger.getRootLogger().removeAppender(crashAndBurnAppender);

Ответы [ 2 ]

14 голосов
/ 13 апреля 2011

Вы можете создать новый Appender , который выдает ошибку AssertionError, когда вы регистрируетесь с уровнем ошибки.

Что-то вроде

class TestAppender extends AppenderSkeleton {
    public void doAppend(LoggingEvent event) {
         if(event.getLevel() == Level.Error) {
              throw new AssertionError("logged at error:" + event.getMessage());
         }
    }
}

В вашем тесте сделать1008 *

Logger.getRootLogger().addAppender(new TestAppender());

Редактировать: как указал Ральф, удалить TestAppender после завершения теста.

0 голосов
/ 18 декабря 2015

Log4j2 решение

Я только что наткнулся на это, но так как я использую версию 2 Log4j, мне пришлось адаптировать код. Это заняло у меня довольно много времени, так как большинство ресурсов о запутанном беспорядке фабрик конфигурации, конфигураторов, контекстов логгера и чего угодно. То, что я сделал, может быть не самым чистым или официальным способом, но это просто .

Определение такого служебного класса с помощью двух открытых статических методов:

private static Appender appender;

private static void enableThrowOnLog(Level level) {
    // Downcast: log4j.Logger -> log4j.core.Logger
    Logger rootLogger = (Logger) LogManager.getRootLogger();

    appender = new ThrowingAppender(level);
    appender.start();
    rootLogger.addAppender(appender);
}

public static void disableThrowOnLog() {
    // Downcast: log4j.Logger -> log4j.core.Logger
    Logger rootLogger = (Logger) LogManager.getRootLogger();

    appender.stop();
    rootLogger.removeAppender(appender);
    appender = null;
}

private static class ThrowingAppender extends AbstractAppender {
    private final Level level;

    public ThrowingAppender(Level level) {
        // Last parameter: ignoreExceptions -- must be false or exceptions will be swallowed
        super("ThrowingAppender", new AbstractFilter() {}, PatternLayout.createDefaultLayout(), false);
        this.level = level;
    }

    @Override
    public synchronized void append(LogEvent event) {
        Level eventLevel = event.getLevel();
        if (eventLevel.isMoreSpecificThan(this.level)) {
            String message = event.getMessage().getFormattedMessage();
            throw new AppenderLoggingException(eventLevel + " level was logged:\n> " + message);
        }
    }
}

В идеале вы вызываете enableThrowOnLog() в методе JUnit 4 @BeforeClass и disableThrowOnLog() в методе @AfterClass, чтобы правильно отменить изменения в глобальной системе журналов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...