是否有最佳做法来比较Go中的非不透明错误值?
大多数代码库似乎将错误视为不透明(操作成功或失败,无法查看导致错误的内部详细信息)。
这使得编写单元测试变得容易,因为您需要做的就是根据预期的错误断言实际错误。除此之外,我见过的人最多的是比较错误字符串,以确保它至少包含一些关键信息。例如:
if err == nil || !strings.Contains(err.Error(), "not found in the Raft configuration") {
t.Fatalf("err: %v", err)
}
但是对于需要额外错误信息的情况(例如在需要指定无效字段名称,值,错误代码以及可能还有一些嵌套错误的表单验证中),您会怎么做?
我不能简单地执行reflect.DeepEqual()
,因为错误将包含唯一的堆栈跟踪,这将使每次比较失败。此外,嵌套错误会使测试逻辑变得更加复杂,并且您需要各种容易出错的逻辑(循环,递归)来比较所需的字段。有没有一种标准的方法来测试这种性质的错误?
答案 0 :(得分:1)
虽然这可能无法回答您关于检查错误的问题,而这些错误并未以正确的方式完成,但至少有一个如何以正确的方式创建和使用错误的示例。
标准库包中通常执行的操作是将错误创建为导出变量,然后可以抛出并比较这些错误。这是一个例子......但它可能是缺乏想象力的。
https://play.golang.org/p/JlpguFn2NX
package main
import (
"errors"
"fmt"
)
var ErrBadIdea = errors.New("that was dumb")
var ErrNoValue = errors.New("not a real value")
func DoSomething(i int) error {
if i == 0 {
return ErrNoValue
}
if i < 0 {
return ErrBadIdea
}
// does something that doesn't like negative or zero values
return nil
}
func main() {
err := DoSomething(-1)
fmt.Println(err == ErrBadIdea, err)
err = DoSomething(0)
fmt.Println(err == ErrNoValue, err)
}
这方面的一个很好的例子是标准库的database/sql
包。
https://godoc.org/database/sql#pkg-variables
这些变量存在,所以你可以这样测试
if err == sql.ErrNoRows { // these are not the rows you are looking for }
它变得更好!
由于error
是interface
,您所要做的就是实现它。这只需要你func Error() string
。请参阅以下示例,并惊叹于interface
s。
https://play.golang.org/p/3RFrxKGkdm
另请阅读以下有关错误的博客。