You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

测试错误处理器日志语句:SLF4J Test日志未填充问题求助

问题:SLF4J Test日志断言失败,日志列表始终为空

我基于流程中抛出的MessagingException负载类型实现了自定义错误日志处理器,代码如下:

@ServiceActivator
public void handleThrowable(Message<Throwable> errorMessage) {

    var throwable = errorMessage.getPayload();
    log.error("Error in Processing. Message: {}", throwable.getMessage(), throwable);

    if (throwable instanceof MessagingException) {
        var messagingException = (MessagingException) throwable;
        var failedMessage = messagingException.getFailedMessage();
        log.error("Failed Message: {}", failedMessage);

        if (!Objects.isNull(failedMessage)) {
            var msg = failedMessage.getPayload();
            var headers = failedMessage.getHeaders();

            if (msg instanceof File) {
                log.error("Failed consuming File: {}", ((File) msg).getAbsolutePath());
            }

            if (msg instanceof String) {
                log.error("Failed to create a CsvEmailInteraction from line {}. Line was: {}", headers.get(IntegrationMessageHeaderAccessor.SEQUENCE_NUMBER), msg);
            }

            if (msg instanceof CsvEmailInteraction) {
                var csvObject = (CsvEmailInteraction) msg;
                log.error("Failed to publish CsvEmailInteraction to Kafka. messageId was: {}", csvObject.getMessageId());
            }
        }
    }
}

我使用SLF4J Test » 1.2.0编写测试代码,但在断言部分尝试获取日志时,日志列表始终未被填充。以下是针对String类型负载的测试代码(其他类型测试逻辑类似):

class DefaultErrorChannelServiceActivatorSpec extends Specification {

    def serviceActivator = new DefaultErrorChannelServiceActivator()
    TestLogger testLogger = TestLoggerFactory.getTestLogger(DefaultErrorChannelServiceActivator.class)

    def "test handleThrowable with MessagingException instance of String"() {
        given:

        // Create a MessagingException with a failed message
        def failedMessage = new GenericMessage<>("This is a failed string message")
        def messagingException = Mock(MessagingException)
        testLogger.clear()

        Message<Throwable> throwableMessage = MessageBuilder.withPayload(messagingException).build()

        when:
        serviceActivator.handleThrowable(throwableMessage)

        then:
        1 * messagingException.getFailedMessage() >> failedMessage
//        def logs = testLogger.getAllLoggingEvents()
//        logs.contains("Failed Message")

    }
}

修复方案

  1. 确保日志绑定唯一性
    测试依赖中仅保留org.slf4j:slf4j-test:1.2.0,排除其他SLF4J绑定(如logback-classic、log4j-slf4j-impl),避免日志被其他实现拦截。

  2. 对齐Logger初始化类
    检查DefaultErrorChannelServiceActivator中的日志实例是否使用自身类初始化:

private static final Logger log = LoggerFactory.getLogger(DefaultErrorChannelServiceActivator.class);

必须和测试中TestLoggerFactory.getTestLogger(...)传入的类一致,否则测试Logger无法捕获目标类的日志。

  1. 补充Mock缺失的方法调用
    处理器会调用throwable.getMessage(),补充该Mock避免空值影响日志输出:
then:
1 * messagingException.getFailedMessage() >> failedMessage
1 * messagingException.getMessage() >> "Test error message"
  1. 使用正确的断言方式
    SLF4J Test提供了更易用的断言方法,替代手动遍历日志事件:
then:
// 验证特定格式的ERROR日志是否被记录
testLogger.errorLogged("Failed Message: {}", failedMessage)
// 验证String负载对应的日志内容
testLogger.errorLogged("Failed to create a CsvEmailInteraction from line null. Line was: This is a failed string message")

(注:SEQUENCE_NUMBER未设置,所以此处为null)

  1. 显式设置日志级别
    确保TestLogger的级别不会过滤ERROR日志(默认级别为INFO,ERROR会被捕获,可显式设置确保):
given:
testLogger.setLevel(Level.ERROR)

内容的提问来源于stack exchange,提问作者Beez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 00:30:21