Go 单元表测试中的错误类型检查

Ale*_*lex 5 testing error-handling unit-testing go

我想根据预期结果的表测试来测试返回的错误类型,如下所示:

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
  }
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,根据发生的错误类型返回不同的错误子类。您可能会想象,编造的 Thesaurus 函数的调用者会以不同的方式处理每种错误类型。

断言返回的错误类型和预期的错误类型相同的惯用方法是什么?

Lin*_*ope 5

使用type开关。

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
    }
}
Run Code Online (Sandbox Code Playgroud)

它绝对不像reflect这样做的方式那么简洁,但我认为它更 Go-ish 和明确。


Ale*_*lex 2

Reflect.TypeOf 的工作如下:

import "reflect"

...

func TestThesaurus(t *Testing) {
  for _, testcase := range tabletest {
    got, err := Thesaurus(testcase.instruction)
    // check error type
    if goterr, wanterr := reflect.TypeOf(err), reflect.TypeOf(testcase.err); 
         goterr != wanterr {
      t.Errorf("For instruction %q, unexpected error: %q. Wanted %q", 
               testcase.instruction, goterr, wanterr)
    }
    // check result type
    if want := testcase.want; got != want {
      t.Errorf("For instruction %q, got %q, want %q.", 
               testcase.instruction, got, want)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

它是否惯用由社区决定。