Log4j2 RoutingAppender 与跨多个线程的 ListAppender

问题描述 投票:0回答:1

(这是我原来问题的后续问题: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
的尝试也都失败了。

我猜我要么遗漏了一些东西,要么误解了如何应用它。

我也尝试过以编程方式执行此操作,但结果有些混乱。

任何帮助将不胜感激,如果这是我以某种方式忽略的简单事情,我会提前道歉。

提前谢谢您!

来源:

java spring log4j2 junit5 maven-surefire-plugin
1个回答
0
投票

当涉及到属性替换时,路由附加器有点特殊:

  • 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());
© www.soinside.com 2019 - 2024. All rights reserved.