Quarkus 新手问题:我有一个 A 类,它使用默认的 Quarkus 日志框架记录一些内容(我相信它是 jboss 日志记录)。接下来我想为 A 编写一个测试类,它必须能够验证 A 生成了哪些日志消息。我如何使用 Quarkus 做到这一点?
您需要使用
io.quarkus.test.InMemoryLogHandler
并将其添加到rootLogger。这会将日志消息存储在内存中,以便以后可以随时访问它们。
例如,请查看此处:https://github.com/quarkusio/quarkus/commit/57fb0cc57bf435bbdb86ca0614bf03dc04bea383
感谢罗伯托的出色建议。然而,我开始使用 LogCaptor 库 (https://github.com/Hakky54/log-captor),它非常适合我的目的。它开箱即用,没有太多麻烦。
除了标准 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)
...
}
正如 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,并且如果您愿意,也可以根据您的需要进行调整。