我有一个包含静态自定义记录器的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
,我使用setter传递给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">
。它只在根记录器中设置,这就是它无法正常工作的原因。