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

如何使用testify断言logrus触发Panic时的错误消息?

使用Logrus时用Testify断言Panic的Message内容

问题场景

使用Logrus日志库时,通过mylogger.Panic()抛出panic,尝试用Testify的PanicsWithError断言panic内容时失败——捕获到的panic值是Logrus的Entry对象,而非预期的错误字符串。

业务代码示例

var mylogger = logrus.WithContext("MyLogger")

func LoadPreparedStatements() {
    db := psql.PsqlClient()
    var err error

    myPreparedStatement, err = db.Prepare("SELECT * FROM mytable")
    if err != nil {
        mylogger.Panic("Loading SQL Prepared Statement Failed")
    }
}

测试代码尝试

PanicsWithError(t, "test", func() {
    LoadPreparedStatements()
})

捕获到的Panic值

Panic value:    &logrus.Entry{Logger:(*logrus.Logger)(0xc0000ba000), Data:logrus.Fields{"context":"MyLogger"}, Time:time.Date(2022, time.November, 1, 21, 49, 27, 889501622, time.Local), Level:0x0, Caller:(*runtime.Frame)(nil), Message:"Loading SQL Prepared Statement Failed", Buffer:(*bytes.Buffer)(nil), Context:context.Context(nil), err:""}

解决方案

Logrus的Panic()方法会将传入内容包装为logrus.Entry对象抛出,因此需要自定义断言逻辑提取并验证Message字段。

方法一:Testify Panics()结合类型断言

用Panics()捕获panic后,对panic值做类型断言,取出Message字段验证:

t.Run("verify panic message", func(t *testing.T) {
    // 先断言会触发panic
    assert.Panics(t, func() {
        LoadPreparedStatements()
    }, "LoadPreparedStatements should panic when DB prepare fails")

    // 捕获panic并验证Message内容
    func() {
        defer func() {
            if r := recover(); r != nil {
                entry, ok := r.(*logrus.Entry)
                assert.True(t, ok, "panic value must be a *logrus.Entry")
                assert.Equal(t, "Loading SQL Prepared Statement Failed", entry.Message)
            }
        }()
        LoadPreparedStatements()
    }()
})

方法二:自定义复用断言函数

封装专门验证Logrus Panic Message的函数,方便多处调用:

func PanicsWithLogrusMessage(t assert.TestingT, expectedMsg string, f assert.PanicTestFunc, msgAndArgs ...interface{}) bool {
    defer func() {
        if r := recover(); r != nil {
            entry, ok := r.(*logrus.Entry)
            if !ok {
                assert.Fail(t, "panic value is not a *logrus.Entry", msgAndArgs...)
                return
            }
            assert.Equal(t, expectedMsg, entry.Message, msgAndArgs...)
            return
        }
        assert.Fail(t, "expected panic but none occurred", msgAndArgs...)
    }()
    f()
    return false
}

// 使用示例
PanicsWithLogrusMessage(t, "Loading SQL Prepared Statement Failed", func() {
    LoadPreparedStatements()
}, "should panic with correct log message")

补充说明

如果不需要保留Logrus上下文信息,也可以在业务代码中直接panic错误对象或字符串;但如果必须保留日志上下文,上述两种方法是更合适的选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 04:40:29