2017-04-04 87 views
2

是否有比較Go中非透明錯誤值的最佳做法?測試非透明錯誤值

大多數代碼庫似乎將錯誤視爲不透明(操作成功或失敗,不知道導致錯誤的內部細節)。

這使得編寫單元測試變得很容易,因爲您需要做的就是根據預期錯誤聲明實際錯誤。除此之外,我見過的人中最多的是比較錯誤字符串,以確保它至少包含一些關鍵信息。例如:

if err == nil || !strings.Contains(err.Error(), "not found in the Raft configuration") { 
    t.Fatalf("err: %v", err) 
} 

但對於那些需要額外的錯誤信息(如表單驗證,你需要指定無效的字段名稱,值,錯誤代碼,可能還有一些嵌套的錯誤太)的情況下,是什麼你做?

我不能簡單地做一個reflect.DeepEqual(),因爲錯誤將包含一個唯一的堆棧跟蹤,每次都會使比較失敗。另外,嵌套錯誤會使測試邏輯更加複雜,您需要各種容易出錯的邏輯(循環,遞歸)來比較所需的字段。有沒有一種測試這種性質錯誤的標準方法?

+1

這些值是不是「確定」,你可以檢查它們的存在,以確保它們被設置,然後將它們設置爲它們的零值('「」','nil'等。 ),然後將其餘部分傳遞給'reflect.DeepEqual'。不理想,但有效。 – mkopriva

回答

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 } 

它變得更好!

因爲errorinterface,所有你需要做的就是實現它。這隻需要你有一個func Error() string。看到下面的例子,並驚歎於interface s的威力。

https://play.golang.org/p/3RFrxKGkdm

而且閱讀有關錯誤以下博客。

https://blog.golang.org/error-handling-and-go

+0

感謝您查看問題。我很好奇你對這種類型的自定義錯誤會認爲「不正確」。當你有一個錯誤需要更多的上下文而不僅僅是一個簡單的錯誤字符串時,有什麼替代方法?如果您有一個返回特定錯誤代碼和失敗原因的JSON端點,就像上面的示例一樣。這隻能通過錯誤變量來實現? – user7467314

+0

問題是,人們編碼並決定「這是一個錯誤的情況下」,所以他們懶洋洋地這樣做「如果有東西{return errors.New(」bad「)}'。然後他們將他們的圖書館張貼在github上供大衆使用。但是,返回的錯誤完全沒有價值,它只會告訴你出錯了。這個問題隨之傳播,人們繼續這樣做,現在我們有一堆無用的錯誤被返回。此外,你可以返回更多有用的錯誤,因爲你只需要實現'Error()'接口。我會用一個例子更新我的答案。 – RayfenWindspear

+0

就處理這些毫無價值的錯誤而言,你可能只需要將它們匹配起來,並希望任何庫拋出它不決定改變措辭。 – RayfenWindspear