簡體   English   中英

如何檢查是否在單元測試中調用了 sync.WaitGroup.Done()

[英]How to check if sync.WaitGroup.Done() is called in unit test

假設我有一個 function 如果它作為 go 例程異步執行:

func f(wg *sync.WaitGroup){
    defer wg.Done()
    // Do sth
}

main(){
    var wg sync.WaitGroup
    wg.Add(1)
    go f(&wg)
    wg.Wait() // Wait until f is done
    // ...
}

如何為f創建一個單元測試以確保wg.Done()

一種選擇是在調用f之后直接在測試中調用wg.Done() 如果f調用wg.Done()失敗,測試會恐慌,這不好。 另一種選擇是為sync.WaitGroup創建一個接口,但這似乎有點奇怪。

如何為 f 創建一個單元測試以確保調用 wg.Done()?

像這樣的東西:

func TestF(t *testing.T) {
    wg := &sync.WaitGroup{}
    wg.Add(1)

    // run the task asynchronously
    go f(wg)

    // wait for the WaitGroup to be done, or timeout
    select {
    case <-wrapWait(wg):
        // all good
    case <-time.NewTimer(500 * time.Millisecond).C:
        t.Fail()
    }
}

// helper function to allow using WaitGroup in a select
func wrapWait(wg *sync.WaitGroup) <-chan struct{} {
    out := make(chan struct{})
    go func() {
        wg.Wait()
        out <- struct{}{}
    }()
    return out
}

您不直接檢查 WaitGroup ,無論如何您都不能這樣做。 相反,您斷言 function 的行為符合預期,給定預期的輸入。

在這種情況下,預期的輸入是 WaitGroup 參數,預期的行為是wg.Done()最終被調用。 這在實踐中意味着什么? 這意味着如果 function 成功,計數為 1 的 WaitGroup 將達到 0 並允許wg.Wait()繼續。

f開頭的語句defer wg.Done()已經確保測試對錯誤或崩潰具有彈性。 添加超時只是為了確保測試將在合理的時間內完成,即它不會讓您的測試套件停頓太久。 就個人而言,我更喜歡使用顯式超時,無論是使用計時器還是使用上下文,以避免有人忘記在 CI 級別設置超時時出現問題。

暫無
暫無

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

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