(这是我原来问题的后续问题:Log4j2 Custom Appender in Maven Surefire:可能跨线程重用?)
我正在尝试通过 JUnit5 在我的应用程序 Spring 应用程序中对来自 Log4j2 的任何日志记录的输出进行单元测试。为了解决这个问题,我创建了一个 JUnit5 扩展,它在每次测试之前创建一个
WriterAppender
,我可以用它来验证任何记录的消息。
Maven 与 Surefire 插件一起使用。默认情况下,Surefire 分叉多个线程以加快测试速度。但是,有人指出,每个测试附加程序还将包含同时运行的其他测试的输出。
(我自己已经证实了这一点。)
建议使用
RoutingAppender
来根据我正在尝试执行的 ListAppender
中存储的值创建 ThreadContext
。
我已经查看了多篇关于创建此类设置的帖子、主题和文章。看起来最好的方法是通过 XML 配置,而不是以编程方式执行此操作,因为我不确定它在概念上是否符合正在尝试的内容。
我尝试了以下 XML 配置(及其变体):
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" name="RoutingForTests">
<Appenders>
<Routing name="Routing">
<Routes pattern="$${ctx:appenderName}">
<Route>
<List name="$${ctx:appenderName}" />
</Route>
</Routes>
</Routing>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Routing" />
</Root>
</Loggers>
</Configuration>
ThreadContext
通过 JUnit5 注册扩展进行设置(正确或不正确),例如
LoggerExtension.java
public class LoggerExtension implements BeforeEachCallback, AfterEachCallback {
// ...
@Override
public void beforeEach(ExtensionContext context) {
// ...
ThreadContext.put("appenderName", context.getUniqueId()); // I've even tried hardcoding this value
// ...
}
public void verifyMessage(String message) {
ListAppender appender = ListAppender.getListAppender(ThreadContext.get("appenderName")); // appender ends up null
// ...
}
}
我还尝试使用硬编码的
ListAppender
名称,并尝试使用相同的查找变量,但使用单个 $ 而不是两个(但我认为这会解析为空白/空值,因为我不认为 ThreadContext
已正确设置,但我不能确定)。我也尝试过将 key
设置为 Route
,但无济于事。
我什至尝试使用
ThreadId
中的 event
,但任何查找 ListAppender
的尝试也都失败了。
我猜我要么遗漏了一些东西,要么误解了如何应用它。
我也尝试过以编程方式执行此操作,但结果有些混乱。
任何帮助将不胜感激,如果这是我以某种方式忽略的简单事情,我会提前道歉。
提前谢谢您!
来源:
当涉及到属性替换时,路由附加器有点特殊:
pattern
元素的Routes
属性会被评估两次(在配置时和每次记录事件时),因此需要像您一样转义$
,Route
计算为新值时,pattern
元素的内容仅计算一次。因此它不需要需要转义$
。您应该使用:
<Routing name="Routing">
<Routes pattern="$${ctx:appenderName}">
<Route>
<List name="${ctx:appenderName}" />
</Route>
</Routes>
</Routing>
要检索特定于测试用途的附加程序:
LoggerContext context = LoggerContext.getContext(false);
RoutingAppender routing = context.getConfiguration().getAppender("Routing");
ListAppender list = routing.getAppenders().get(extensionContext.getUniqueId());