I want to test the type of the error returned against a table test of expected results, like so:
var tabletest = []struct{
instruction string
want string
err error
}{
{"synonym for hi", "hello", nil}, // input, retval, errtype
{"synonym for hig", "", TranslationError{}},
{"sssnymm for hi", "", InstructionError{}},
}
func TestThesaurus(t *Testing) {
for _, testcase := range tabletest {
got, err := Thesaurus(testcase.instruction)
// check error type
// check result type
}
}
In the example above, different error sub-classes are returned based on the type of error that occurred. You may imagine that the caller of the made-up Thesaurus function would handle each error type differently.
What is the idiomatic way to assert that the type of error returned, and the type of error expected, are the same?
Use a type
switch.
func TestThesaurus(t *Testing) {
for _, testcase := range tabletest {
got, err := Thesaurus(testcase.instruction)
// Don't use && because we want to trap all cases where err is nil
if err == nil {
if testcase.err != nil {
// failure
}
continue
}
switch err.(type) {
case TranslationError:
if _,ok := (testcase.err).(TranslationError); !ok {
// failure
}
case InstructionError:
if _,ok := (testcase.err).(InstructionError); !ok {
// failure
}
default:
// Unrecognized error, failure
}
}
It's definitely not as succinct as the reflect
way of doing it, but I think it's more Go-ish and explicit.
There's also this idiom:
In Thesaurus...
import "errors"
var (
TranslationError = errors.New("")
InstructionError = errors.New("")
)
In Testcase...
if err != testcase.err {
}
However, I think in this idiom the errors must be defined in advance (i.e. the message cannot be changed).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With