2017-02-23 119 views
2

我很難找出慣用的在golang中編寫可測試代碼的方法。我明白接口及其在測試中的重要性,但我還沒有弄清楚如何模擬/測試外部結構依賴關係。嘲笑golang中的外部結構依賴關係

作爲一個例子,我編寫了下面的代碼來模擬在GitHub上創建一個請求的包裝器。

type GitHubService interface { 

} 

type gitHubService struct { 
    CreatePullRequest(...) (PullRequest,error) 
} 

func (s gitHubService) CreatePullRequest(...) (PullRequest,error) { 
    tp := github.BasicAuthTransport{ 
     Username: strings.TrimSpace(/*.....*/), 
     Password: strings.TrimSpace(/*.....*/), 
    } 

    client := github.NewClient(tp.Client()) 
    pr,err := client.Repositories.CreatePullRequest(...) 

    ... 
} 

func TestPullRequest(t *testing.T) { 
    service := gitHubService{} 
    pr,err := service.CreatePullRequest(...) 
    ... 
} 

如果我在寫一個單元測試GitHubService.CreatePullRequest(...)我想嘲笑調用client.Repositories.CreatePullRequest(...)甚至可能github.NewClient(...)返回,我可以控制mock實現。

使用諸如gomock之類的工具,您似乎對結構和包函數感到失望。

處理這種情況的慣用方法是什麼?我非常習慣於控制反轉以及依賴注入和服務定位器等不同的模式,但我無數次聽說這不是慣用的。

+0

單元測試應該測試CreatePullRequest的'邏輯'獨自一人,我對集成測試不感興趣。 – TheJediCowboy

+0

我在說的是,這裏沒有顯示的邏輯來測試 - 一切都發生在github包內,它有自己的測試。如果你確實在'''後面隱藏了額外的邏輯,那麼將它們拆分成單獨的部分進行測試。 – JimB

+0

@JimB如果我將'...'後面的邏輯分解爲自己的測試,我正在測試這些東西,但不是'CreatePullRequest(...)'中的邏輯。我仍然想要一個單元測試來測試這個代碼單元的邏輯流程。 – TheJediCowboy

回答

3

Go的一個重要設計特徵是去耦Watch this great talk from Bill Kennedy about that topic)。在你的方法裏面有一些依賴關係,可以分離。這種耦合方法使得它不是真正可測試的。

件事你應該重構:

  • tp := github.BasicAuthTransport:你不應該初始化方法的內部授權。它應該作爲參數進入你的gitHubService。在您的方法調用中,您可以通過s.tp訪問ist。您也可以將其作爲該方法的輸入參數。
  • github.NewClient() and client.Repositories.CreatePullRequest(...)剛剛閱讀了Peter Bourgon Make dependencies explicit!的golang最佳實踐。另一種方法是創建一個包含所有被調用函數的接口。這個接口應該是你的方法的輸入。

當你的代碼解耦後,你可以模擬一切非常簡單。如果你使用接口作爲輸入,你可以創建一個模擬結構來實現接口。如果明確地顯示依賴關係,則可以覆蓋它們。在最後一種情況下,用於存儲調用值的代碼並不那麼幹淨,但它也可以工作。慣用的方式是使用接口。

3

我有一個類似的問題,看起來像,你有唯一的選擇是在另一層之間的哪個會打電話給你的「unmockable」客戶端。

例如,爲嘲諷govmi客戶機(VMware的客戶端SDK用於golang),我必須有一個「myCustomClient」有接口和結構做出govmi.Client.AnyMethod電話..

然後我可以生成嘲笑爲「myCustomClient」。

mockgen -source myCustomClient.go -package mypackage的-destination myCustomClientMock.go

您可以通過安裝它:有獲得github.com/golang/mock