Chapter 9. Asynchronous Testing
One of the trickiest aspects of testing is dealing safely with asynchronous behavior; that is, things that happen on a different thread from the one executing the test. If handled badly, tests for off-thread behavior can be slow, brittle, or prone to leaking state.
The fundamental problem when dealing with asynchronous behavior is that assertions need to be delayed until the other thread has completed its work. A naïve approach is to simply sleep the main thread for long enough that other threads can complete their work. But how long is long enough? Sleeping the thread tends to result in tests that fail intermittently on different machines under different conditions or run unnecessarily slowly because they sleep far longer than is typically necessary.
Other, better approaches are to either block or poll until the result of the off-thread process is ready. Spock offers constructs that can help with both of those approaches.
One simple and highly effective way to deal with asynchronous behavior is to use some kind of blocking construct that allows the test to ensure the asynchronous behavior has completed before making assertions about the result.
Spock has two blocking constructs in the
spock.util.concurrent package that you can use to capture values generated by asynchronous processes:
BlockingVariable, which captures a single value, and
BlockingVariables (note the plural), which can capture multiple values.