比较Go中的2个错误以进行单元测试

r3i60tvu  于 2023-08-01  发布在  Go
关注(0)|答案(2)|浏览(106)

我遇到了一个问题,如下所示:比较编写单元测试时的2个错误

package main

import (
    "errors"
    "fmt"
    "reflect"
    
    "github.com/google/go-cmp/cmp"
    "github.com/google/go-cmp/cmp/cmpopts"
)

func main() {
    er1 := errors.New("database name is not exists")
    er2 := errors.New("database name is not exists")
    
    result1 := reflect.DeepEqual(er1, er2)
    fmt.Println("reflect: ", result1)
    
    result2 := cmp.Equal(er1, er2, cmpopts.EquateErrors())
    fmt.Println("compare: ", result2)
    
    result3 := errors.Is(er1, er2)
    fmt.Println("errorIs: ", result3)
}

字符串
上面代码的输出是:

reflect:  true
compare:  false
errorIs:  false


我想比较2个错误,reflect.DeepEqual(er1, er2)是我应用的第一种方法,这个方法产生了我想要的输出,但是这个方法有一个来自go lint的警告:

avoid using reflect.DeepEqual with errorsdeepequalerrors


在谷歌搜索之后,有些人告诉我一些方法:

  • 使用cmp包进行比较:cmp.Equal(er1, er2, cmpopts.EquateErrors())
  • 使用错误包进行比较:errors.Is(er1, er2)

但是,上述两种方法都不能产生与第一种方法(使用reflect.DeepEqual)相同的结果。我如何在没有来自go lint的警告的情况下比较2个错误,并产生像reflect.DeepEqual Tks一样的结果

8yoxcaq7

8yoxcaq71#

根据您编写测试的方式,您可能依赖于reflect.DeepEqual()并忽略linter警告;
缺点是:你开始依赖于你返回的错误的内部结构。
在我们编写的测试代码中,我们使用以下模式之一:

  • 大多数情况下,我们只是将误差与nil进行比较;
  • 在某些情况下,我们的函数返回预定义的错误值,我们测试这些特定的值:
package pkg

var ErrUnboltedGizmo = errors.New("gizmo is unbolted")

// in test functions, depending on the case :
if err == pkg.ErrUnboltedGizmo { ...
// or :
if errors.Is(err, pkg.ErrUnboltedGizmo) { ...

字符串

  • 当我们的产品代码要求发现特定的错误时(常见的用例是io.EOF),我们编写代码来忠实地 * Package * 已知的错误,并且我们使用errors.Is()(在产品代码和测试代码中),
  • 当仅在测试中需要松散地确认错误匹配某个东西而不是其他东西时(例如:Parse error而不是File not found),我们只需在错误消息中搜索字符串:
if err == nil || !strings.Contains(err.Error(), "database name is not exists") {
    t.Errorf("unexpected error : %s", err)
}

dsf9zpds

dsf9zpds2#

我发现有用的是使用cmppopts.IgnoreFields的cmp.diff来忽略特定的错误字段,这些错误字段会导致你详细的问题,然后我只需使用string.Contains或任何我发现合适的错误来检查错误。
它是这样的:

if diff := cmp.Diff(expected, got, cmpopts.IgnoreFields(expected, "ErrorField")); diff != "" { 
          // found diff not including the error
}

字符串
现在只检查它们自己的错误,就是这样。
是的,我知道你已经标记了一个解决方案,但也许它会帮助别人:)

相关问题