2

When using logrus, how do you assert for panic using an assertion library like testify?

Take the following code for an example:

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")
    }
}

When writing test with testify, I can only catch the following error:

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

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:""}

Is there any way to test for the returned message?

PressingOnAlways
  • 11,948
  • 6
  • 32
  • 59

1 Answers1

0

I couldn't find any way to do this except write my own test. I used the following code to implement an assertion that tests the logrus response. It might have issues if the error raised is not from logrus, but it allowed me to write the assertions I was looking to have.

type tHelper interface {
    Helper()
}

// didPanic returns true if the function passed to it panics. Otherwise, it returns false.
func didPanic(f assert.PanicTestFunc) (didPanic bool, message interface{}, stack string) {
    didPanic = true

    defer func() {
        message = recover()
        if didPanic {
            stack = string(debug.Stack())
        }
    }()

    // call the target function
    f()
    didPanic = false

    return
}
func PanicsWithLogrusError(t assert.TestingT, errString string, f assert.PanicTestFunc, msgAndArgs ...interface{}) bool {
    if h, ok := t.(tHelper); ok {
        h.Helper()
    }

    funcDidPanic, panicValue, panickedStack := didPanic(f)
    if !funcDidPanic {
        return assert.Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...)
    }
    panicErr, ok := panicValue.(*logrus.Entry)

    if !ok || panicErr.Message != errString {
        return assert.Fail(t, fmt.Sprintf("func %#v should panic with logrus error message:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, errString, panicErr.Message, panickedStack), msgAndArgs...)
    }

    return true
}
    PanicsWithLogrusError(t, "Loading SQL Prepared Statement Failed", func() {
        LoadPreparedStatements()
    })

The above makes the test pass.

PressingOnAlways
  • 11,948
  • 6
  • 32
  • 59