Testing multi-threaded code can become arbitrarily complex. However, in most cases, it doesn’t need to. The following formula should cover the majority of cases:
- Unit test the “work” performed by each thread in isolation. (If you absolutely need to, write some integration tests.)
- Unit test the multi-threaded code, focusing on the concurrent parts, i.e., verify that the correct sequence of operations is happening using mocks or spies.
- If the above takes too long. Move the test out of the unit test suite into a suite that runs slower tests.
- Alternatively, write a slower test that aims for eventual consistency, i.e., lets the threads do whatever they want and they verifies the expected end state.