[英]How to check if sync.WaitGroup.Done() is called in unit test
Let's say I have a function if that is executed asynchronous as a go routine:假设我有一个 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
// ...
}
How would I create a unit test for f
that makes sure wg.Done()
is called?如何为
f
创建一个单元测试以确保wg.Done()
?
One option is to call wg.Done()
in the test directly after the f
is called.一种选择是在调用
f
之后直接在测试中调用wg.Done()
。 If f
fails to call wg.Done()
the test will panic which is not nice.如果
f
调用wg.Done()
失败,测试会恐慌,这不好。 Another option would be to create an interface for sync.WaitGroup
but that seems a bit weird.另一种选择是为
sync.WaitGroup
创建一个接口,但这似乎有点奇怪。
How would I create a unit test for f that makes sure wg.Done() is called?
如何为 f 创建一个单元测试以确保调用 wg.Done()?
Something like this:像这样的东西:
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
}
You don't inspect the WaitGroup directly, which you can't do anyway.您不直接检查 WaitGroup ,无论如何您都不能这样做。 Instead you assert that the function behaves as expected , given the expected input.
相反,您断言 function 的行为符合预期,给定预期的输入。
In this case, the expected input is the WaitGroup argument and the expected behavior is that wg.Done()
gets called eventually.在这种情况下,预期的输入是 WaitGroup 参数,预期的行为是
wg.Done()
最终被调用。 What does that mean, in practice?这在实践中意味着什么? It means that if the function is successful a WaitGroup with count 1 will reach 0 and allow
wg.Wait()
to proceed.这意味着如果 function 成功,计数为 1 的 WaitGroup 将达到 0 并允许
wg.Wait()
继续。
The statement defer wg.Done()
at the beginning of f
already makes sure that the test is resilient to errors or crashes. f
开头的语句defer wg.Done()
已经确保测试对错误或崩溃具有弹性。 The addition of a timeout is simply to make sure the test will complete within a reasonable time, ie that it doesn't stall your test suite for too long.添加超时只是为了确保测试将在合理的时间内完成,即它不会让您的测试套件停顿太久。 Personally, I prefer using explicit timeouts, either with timers or with contexts, to avoid problems if someone forgets to set timeouts at the CI level.
就个人而言,我更喜欢使用显式超时,无论是使用计时器还是使用上下文,以避免有人忘记在 CI 级别设置超时时出现问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.