Как я могу протестировать свои сообщения журнала с помощью testng? - PullRequest
0 голосов
/ 31 мая 2019

Мы используем testng в качестве основы тестирования.Мы также используем Lombok @ Log4j2 для создания экземпляров наших объектов журнала.Мне нужно протестировать некоторый код, который регистрирует определенные сообщения при определенных условиях.

Я видел примеры использования junit и Mockito.Но я не могу найти, как это сделать в testng.Переключение на джунит не вариант.

Редактировать

Я реализовал класс (CaptureLogger), который расширяет AbstractLogger

import org.apache.logging.log4j.spi.AbstractLogger;

public class CaptureLogger extends AbstractLogger {
    ...
}

Я не могу подключить его к регистратору для тестируемого класса.

CaptureLogger customLogger = (CaptureLogger) LogManager.getLogger(MyClassUnderTest.class);

генерирует сообщение об ошибке:

java.lang.ClassCastException: org.apache.logging.log4j.core.Logger cannot be cast to CaptureLogger

Я обнаружил, что LogManager.getLogger возвращает интерфейс Logger, а не объект Logger (который реализует интерфейс Logger).

Как я могу создать экземпляр моего CaptureLogger?

1 Ответ

1 голос
/ 31 мая 2019

Пока вы используете Lombok для генерации логгеров, вы не можете многое сделать на уровне самого исходного кода с помощью данных инструментов. Например, если вы размещаете аннотацию @Log4j2, она генерирует:

private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);

Скомпилированный код уже поставляется с этой строкой.

Вы можете попробовать смоделировать метод LogManager.getLogger с PowerMockito, но мне не очень нравятся такие инструменты. Заявив об этом, хотя это может быть жизнеспособным направлением.

Существует несколько способов работы с самой платформой.

Один из способов (и я не знаком с Log4j2 конкретно, но он должен предлагать эту возможность - я сделал нечто подобное с Log4j 1.x много лет назад) - предоставить собственную реализацию logger и связать ее с фабрикой logger. на уровне конфигураций Log4j2. Теперь, если вы сделаете это, то код, сгенерированный lombok, вернет ваш экземпляр logger, который может запомнить сообщения, которые были зарегистрированы на разных уровнях (это пользовательская логика, которую вы должны будете реализовать на уровне Logger).

Тогда у регистратора будет метод public List<String> getResults(), и вы будете вызывать следующий код на этапе проверки:

   public void test() {
     UnderTest objectUnderTest = ...
     //test test test

     // verification
     MyCustomLogger logger = (MyCutomLogger)LogManager.getLogger(UnderTest.class);

     List<String> results =  logger.getResults();
     assertThat(results, contains("My Log Message with Params I expect or whatever");

   }

Еще один похожий способ, который я могу придумать, - это создание собственного приложения, которое будет запоминать все сообщения, отправленные во время теста. Затем вы могли бы (декларативно или программно связать этого приложения с Logger, полученным LogFactory.getLogger для тестируемого класса (или также для других классов в зависимости от ваших реальных потребностей).

Затем дайте тесту поработать, а когда дело доходит до проверки - получите ссылку на appender из системы log4j2 и запросите результаты с помощью некоторого метода public List<String> getResults(), который должен существовать в appender в дополнение к методам, которые он должен реализовать. чтобы подчиняться Контракту Аппендера.

Итак, тест может выглядеть примерно так:

public void test () {
     MyTestAppender app = createMemorizingAppender();
     associateAppenderWithLoggerUnderTest(app, UnderTest.class);
     UnderTest underTest = ...

     // do your tests that involve logging operations

     // now the verification phase:

     List<String> results =  app.getResults();
     assertThat(results, contains("My Log Message with Params I expect or whatever");


}
...