如何使用 Quarkus 拦截日志消息以进行测试

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

Quarkus 新手问题:我有一个 A 类,它使用默认的 Quarkus 日志框架记录一些内容(我相信它是 jboss 日志记录)。接下来我想为 A 编写一个测试类,它必须能够验证 A 生成了哪些日志消息。我如何使用 Quarkus 做到这一点?

logging quarkus
4个回答
4
投票

您需要使用

io.quarkus.test.InMemoryLogHandler
并将其添加到rootLogger。这会将日志消息存储在内存中,以便以后可以随时访问它们。

例如,请查看此处:https://github.com/quarkusio/quarkus/commit/57fb0cc57bf435bbdb86ca0614bf03dc04bea383


2
投票

感谢罗伯托的出色建议。然而,我开始使用 LogCaptor 库 (https://github.com/Hakky54/log-captor),它非常适合我的目的。它开箱即用,没有太多麻烦。


1
投票

除了标准 Quarkus 平台之外,该解决方案没有任何外部依赖项。此外,它使用默认的日志解决方案 JBoss。

以下所有代码都是用 Kotlin 编写的,并使用 JUnit 5

首先,您需要一个扩展的类

java.util.logging.Handler

import java.util.logging.Handler
import java.util.logging.Level
import java.util.logging.LogRecord

class LogCaptureHandler : Handler() {
    private val capturedMessages: MutableList<String> = mutableListOf()

    init {
        level = Level.ALL
    }

    override fun publish(record: LogRecord) {
        capturedMessages.add(record.message)
    }

    override fun flush() {}

    override fun close() {}

    fun getCapturedMessages(): List<String> {
        return capturedMessages.toList()
    }
}

现在,在您的测试中,您需要为要捕获日志的类创建一个

java.util.logging.Logger
变量并实例化
LogCaptureHandler
:

private val myClassWithLogger = Logger.getLogger("full.package.path.to.ClassWithLogger")
private final val logCaptureHandler = LogCaptureHandler()

此外,用

@TestInstance(Lifecycle.PER_CLASS)
注释您的测试类并配置测试设置:

@BeforeAll
fun setup() {
    myClassWithLogger.addHandler(logCaptureHandler)
}

现在,在您的测试方法中,您可以调用要捕获日志的方法并检查日志是否正确记录:

@Test
fun myTestMethod() {
    myClass.methodThatLogs()

    // do the asserts
    assertTrue(logCaptureHandler.getCapturedMessages().size() > 0)
    ...

}

0
投票

正如 Robert Cortez 所建议的,您可以利用 Quarkus GitHub 存储库中的此类:InMemoryLogHandler.java 在单元测试期间从测试的类中检索日志。您可以简单地复制它并将其用作测试的实用程序。

这是一个用法示例,假设您在测试范围内的 util 目录中拥有该类:

@ApplicationScoped
@Slf4j
public class MyService{
    public void myMethod() {
      log.info("Log message");
  }
}

然后你的测试课就会像这样

@ExtendWith(MockitoExtension.class)
class MyServiceTest {

@InjectMocks
MyService myService;

@Test
@DisplayName("Verify log message success")
void verifyLogMessage() {
    String expectedLogMessage = "Log message";
    InMemoryLogHandler inMemoryLogHandler = new InMemoryLogHandler(record -> record.getMessage().contains(expectedLogMessage));
    LogManager.getLogManager().getLogger("").addHandler(inMemoryLogHandler);

    myService.myMethod();
    List<LogRecord> logRecords = inMemoryLogHandler.getRecords();
    assertEquals(expectedLogMessage, logRecords.get(0).getMessage());
}

@Test
@DisplayName("Verify log message fails")
void verifyLogMessageFails() {
    String expectedLogMessage = "Log";
    InMemoryLogHandler inMemoryLogHandler = new InMemoryLogHandler(record -> record.getMessage().contains(expectedLogMessage));
    LogManager.getLogManager().getLogger("").addHandler(inMemoryLogHandler);

    myService.myMethod();
    List<LogRecord> logRecords = inMemoryLogHandler.getRecords();
    assertEquals(expectedLogMessage, logRecords.get(0).getMessage());
}

@Test
@DisplayName("Verify log message fails IndexOutOfBoundsException")
void verifyLogMessageFailsIndexOutOfBoundsException() {
    String expectedLogMessage = "Log message bigger than the logged one";
    InMemoryLogHandler inMemoryLogHandler = new InMemoryLogHandler(record -> record.getMessage().contains(expectedLogMessage));
    LogManager.getLogManager().getLogger("").addHandler(inMemoryLogHandler);

    myService.myMethod();
    List<LogRecord> logRecords = inMemoryLogHandler.getRecords();
    assertEquals(expectedLogMessage, logRecords.get(0).getMessage());
}

}

第一个测试将通过,因为预期的 LogMessage 和实际记录的消息相同,但第二个测试将失败并显示此控制台输出

INFO [int.cas.exc.MyService](主要)日志消息

org.opentest4j.AssertionFailedError:
预期:日志
实际:记录消息

第三个将抛出以下内容:

java.lang.IndexOutOfBoundsException:索引 0 超出长度 0 的范围

因为处理程序没有拦截“Log message”字符串,但期望获得“Log message more than thelogginged message”并将其添加到记录中 因此,如果您使用此类,请注意如何指示 InMemoryLogHandler,并且如果您愿意,也可以根据您的需要进行调整。

© www.soinside.com 2019 - 2024. All rights reserved.