У меня есть Spring Boot @Component, который содержит статический пользовательский регистратор, и мне нужно проверить сообщения журнала, созданные внутри этого компонента. Это компонент:
@Component
public class CustomComponent {
private static CustomLogger logger = CustomLogger.getLogger(CustomComponent.class);
public void setLogger(CustomLogger logger) {
CustomComponent.logger = logger;
}
public void doSomething(){
logger.info("This is a test from CustomComponent");
}
}
И это CustomLogger (этот код упрощен. На самом деле нам нужен пользовательский регистратор, потому что нам нужно делать другие вещи внутри него, но они не имеют отношения к этой проблеме):
public class CustomLogger {
private final ExtendedLoggerWrapper log;
private CustomLogger(final Logger log) {
this.log = new ExtendedLoggerWrapper((AbstractLogger) log, log.getName(), log.getMessageFactory());
}
public static synchronized CustomLogger getLogger(final Class<?> clazz) {
final Logger wrapped = LogManager.getLogger(clazz);
return new CustomLogger(wrapped);
}
public void info(Object message) {
if (log.isInfoEnabled()) {
log.info(message);
}
}
}
Это файл log4j2:
<Configuration status = "warn" name = "CustomLogger" packages = "">
<Appenders>
<List name = "List1" />
<Console name = "APPLICATION" target = "SYSTEM_OUT">
<PatternLayout pattern = "%d{ISO8601} %5p %m (%F:%L)%n"/>
<Filters>
<!-- This allows DEBUG, INFO, WARN, ERROR AND FATAL -->
<ThresholdFilter level = "DEBUG" onMatch = "ACCEPT" onMismatch = "DENY"/>
</Filters>
</Console>
</Appenders>
<Loggers>
<Logger name = "com.example.demo" level = "DEBUG" additivity = "false">
<AppenderRef ref = "APPLICATION"/>
</Logger>
<Root level = "WARN">
<AppenderRef ref = "APPLICATION"/>
<AppenderRef ref = "List1" />
</Root>
</Loggers>
</Configuration>
В моем классе JUnit у меня есть компонент @Autowired, и у меня есть ListAppender, полученный с помощью LoggerContextRule. В setup() я создаю mockLogger, который передаю в CustomComponent с помощью сеттера.
Это код моего теста JUnit:
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
@Autowired
CustomComponent component;
@ClassRule
public static LoggerContextRule context = new LoggerContextRule("log4j2.xml");
private ListAppender listAppender;
@Before
public void setup(){
CustomLogger mockLogger = CustomLogger.getLogger(this.getClass());
component.setLogger(logger);
listAppender = context.getListAppender("List1").clear();
}
@Test
public void testCustomComponent() {
component.doSomething();
final List<LogEvent> events = listAppender.getEvents();
assertThat(events, hasSize(1));
}
}
Я ожидал, что listAppender запишет события в mockLogger, но вместо этого он пуст и тест не проходит:
java.lang.AssertionError:
Expected: a collection with size <1>
but: collection size was <0>
Я не понимаю, какую ошибку я делаю, будь то проблема контекста - который может отличаться в классе JUnit и в @Component - или что-то еще.
Я потратил огромное количество времени, пытаясь прочитать официальную документацию log4j2 или пытаясь найти похожие проблемы здесь, в Stackoverflow, но безуспешно.
Решение найдено. Иногда просто записывая свою проблему и пытаясь резюмировать ее, вы получаете прозрение. Я забыл добавить <AppenderRef ref = "List1"> в правый регистратор. Он был установлен только в корневом регистраторе и поэтому не работал.
Collection$UnmodifiableRandomAccessList с size = 0.
В основном List<LogEvent> events пуст.
Вот почему вы получаете ошибку.
Да. У меня вопрос, почему этот список пуст.
Где код для getEvents ()?
Я нашел решение. Иногда просто записывая свою проблему и пытаясь резюмировать ее, вы получаете прозрение. Я забыл добавить <AppenderRef> в правый регистратор в файле log4j2.xml. Дело было только в Root logger.




Что listAppender.getEvents (); возвращение?