Soheil Hassas Yeganeh's solution is usually a good way, or at least something like that. But this is an API change, and it can create some overhead for the caller (although not so much: the caller does not need to transmit the Done channel if he does not need the caller). However, there are times when you do not need such an ACK system.
I highly recommend the Gomega test suite for this kind of problem. It is designed to work with Ginkgo , but can be used autonomously. It includes excellent async support using Consistently and Eventually .
However, while Gomega works well with testing systems other than BDD (and integrates perfectly with testing ), this is a pretty big thing and can be a commitment. If you just want one part, you can write your own version of these statements. I recommend using the Gomega approach, although this is a survey, not just a dream (it is still sleeping, it is impossible to fix it without remodeling your API).
Here's how to look at things in testing. You create a helper function, for example:
http://play.golang.org/p/qpdEOsWYh0
const iterations = 10 const interval = time.Millisecond func Consistently(f func()) { for i := 0; i < iterations; i++ { f()
Obviously, you can customize the iteration and spacing to suit your needs. (Gomega uses a timeout of 1 second, polling every 10 ms.)
The disadvantage of any Consistently implementation is that regardless of your timeout, you should eat that every test run. But in fact this does not happen. You have to decide how much time is enough to not happen. Whenever possible, it's nice to test your test on Eventually , as it can speed up.
Eventually little more complicated, since you need to use recover to catch the panic until it succeeds, but itβs not so bad. Something like that:
func Eventually(f func()) { for i := 0; i < iterations; i++ { if !panics(f) { return } time.Sleep(interval) } panic("FAILED") } func panics(f func()) (success bool) { defer func() { if e := recover(); e != nil { success = true } }() f() return }
Ultimately, this is just a slightly more complex version of what you have, but it turns logic into a function so that it reads a little better.