簡體   English   中英

在Go中實現測試模擬的首選方式是什么?

[英]What is the preferred way to implement testing mocks in Go?

我在Go中構建了一個簡單的CLI工具,用作各種密碼存儲(Chef Vault,Ansible Vault,Hashicorp Vault等)的包裝。 這部分是作為熟悉Go的練習。

在解決這個問題時,我遇到了編寫測試的情況,發現我需要為很多事情創建interfaces ,只是為了能夠模擬依賴關系。 這樣,為了進行測試,一個相當簡單的實現似乎有很多抽象。

但是,我最近在閱讀《 Go編程語言》,並找到了一個示例,其中他們以以下方式模擬了依賴關系。

func Parse() map[string]string {

    s := openStore()

    // Do something with s to parse into a map…

    return s.contents
}

var storeFunc = func openStore() *Store {
    // concrete implementation for opening store
}


// and in the testing file…


func TestParse(t *testing.T) {
    openStore := func() {
        // set contents of mock…
    } 

    parse()

    // etc...

}

因此,為了進行測試,我們將這個具體的實現存儲在一個變量中,然后我們可以在測試中實質上重新聲明該變量,並使它返回所需的內容。

否則,我將為此創建一個interface (盡管當前只有一個實現)並將其注入Parse方法。 這樣,我們可以模擬它進行測試。

所以我的問題是:每種方法的優點和缺點是什么? 什么時候更適合為模擬目的創建接口,而不是將具體函數存儲在變量中以便在測試中重新聲明?

沒有答案的“正確方法”。

說了這么多,我發現interface方法比定義一個函數變量並為測試設置它更加通用和清晰。

以下是有關原因的一些評論:

  • 如果您需要模擬多個函數(在您的示例中,它只是一個函數),那么function variable方法將無法很好地擴展。

  • 與使最終隱藏在實現中的功能變量相反,該interface使該功能/模塊的行為更加清楚。

  • interface允許您注入帶有狀態(結構)的類型,這對於配置模擬的行為可能有用。

對於簡單的情況,您當然可以依靠“函數變量”方法,而對於更復雜的功能,可以使用“接口”,但是如果您希望保持一致並只使用一種方法,則可以使用“接口”。

為了進行測試,我傾向於使用您描述的模擬方法,而不是創建新的接口。 原因之一是AFAIK, 沒有直接的方法來識別哪些結構實現了接口 ,如果我想知道模擬是否在做正確的事情,這對我來說很重要。

這種方法的主要缺點是,該變量本質上是程序包級別的全局變量(即使未導出)。 因此,聲明全局變量的所有缺點都適用。

在您的測試中,您肯定會希望在測試完成后使用deferstoreFunc重新分配回其原始的具體實現。

var storeFunc = func *Store {
    // concrete implementation for opening store
}

// and in the testing file…
func TestParse(t *testing.T) {
    storeFuncOriginal := storeFunc
    defer func() {
        storeFunc = storeFuncOriginal
    }()

    storeFunc := func() {
        // set contents of mock…
    } 

    parse()

    // etc...
}

順便說一下, var storeFunc = func openStore() *Store不會編譯。

我以不同的方式解決這個問題。 特定

function Parse(s Store) map[string] string{
  // Do stuff on the interface Store
}

您有幾個優點:

  1. 您可以根據需要使用模擬或存根存儲。
  2. 恕我直言,代碼變得更加透明。 僅簽名就清楚需要Store實現。 而且,打開商店不需要對代碼進行錯誤處理。
  3. 代碼文檔可以更加簡潔。

但是,這很明顯:解析是可以附加到商店的函數,它比解析周圍的商店更有意義。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM