![](/img/trans.png)
[英]How to write a unit test to check copy constructor is in sync with class properties?
[英]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.