Although I am aware that it might not be idiomatic to panic in Go, I would like to test to ensure a function panics under certain conditions and not in others.
An example of the function.
func PanicOnErr(potentialErr error) {
if potentialErr != nil {
panic(potentialErr)
}
}
The following is an implementation for checking if the function will panic.
func InvocationCausedPanic(f interface{}, params ...interface{}) bool {
// Obtain the function's signature.
reflectedFunc := reflect.ValueOf(f)
funcType := reflect.TypeOf(f)
if funcType.NumIn() != len(params) {
panic("InvocationCausedPanic called with a function and an incorrect number of parameter(s).")
}
reflectedParams := make([]reflect.Value, len(params))
for paramIndex, paramValue := range params {
expectedType := funcType.In(paramIndex)
actualType := reflect.TypeOf(paramValue)
if actualType != expectedType {
errStr := fmt.Sprintf("InvocationCausedPanic called with a mismatched parameter type [parameter #%v: expected %v; got %v].", paramIndex, expectedType, actualType)
panic(errStr)
}
reflectedParams[paramIndex] = reflect.ValueOf(paramValue)
}
return invoke(reflectedFunc, reflectedParams)
}
func invoke(reflectedFunc reflect.Value, reflectedParams []reflect.Value) (panicked bool) {
defer func() {
if r := recover(); r != nil {
panicked = true
}
}()
reflectedFunc.Call(reflectedParams)
return
}
Calling either of the following will cause the type-check to fail.
InvocationCausedPanic(PanicOnErr, errors.New("Some error."))
InvocationCausedPanic(PanicOnErr, nil)
However, it seems possible to call PanicOnErr
using both nil
and something generate by calling errors.New
(seems to be of type *errors.errorString
).
As such, is there a way to check if the type of some parameter is suitable for invoking some function?
While I know it is possible to use defer and recover to more simply test the function, I am curious as to whether it is possible to write a general function that can accept any function and parameters and determine whether it resulted in a panic (assuming the function completes).
Relevant Go Playground: http://play.golang.org/p/qUG7OGuIbD