I am looking for general thoughts and/or links on the topic in general, although my specific motivation at the moment are UI tasks related to progress reporting using either BackgroundWorker and / or TPL. My experience level with async programming in general is novice. The testing tools I know best are NUnit and Rhino.
Some brain storming ideas off the top of my head:
- Don't bother - it's too complicated and you just wind up testing the BGW or TPL.
- Make some sort of fake or mock.
- Use EventWaitHandles
Unit testing asynchronous code is not the simplest thing in the world, as I learned when writing unit tests for my Nito.Async library. :)
First, you want to define what you actually want to test. Do you just want to test whether the asynchronous action is performed, or do you want to ensure that your BGW/tasks are properly synchronizing their UI progress reporting?
Testing the action is pretty straightforward: just wait until the action is complete and then check for postconditions. (However, be aware that the BGW
RunWorkerCompleted
will be raised on aThreadPool
thread unless you give it a synchronization context like the example below).Testing proper synchronization (e.g., that each piece of code is running on the correct thread) is more complex.
For each test you'll need to establish a synchronization context. This will be mocking the UI synchronization context. My Nito.Async library may help with that; it has an
ActionThread
which is a separate thread that contains a synchronization context suitable for owning EAP components (e.g., BGW) and scheduling tasks (e.g.,TaskScheduler.FromCurrentSynchronizationContext
).It can be used like this (using an MSTest example):
I find
Thread.CurrentThread.ManagedThreadId
andThread.CurrentThread.IsThreadPoolThread
to be the easiest ways to check for proper synchronization. If your test code is run from withinActionThread.Do
, then it should synchronize its progress updates (and completion notification) to thatActionThread
.A lot of the Nito.Async unit tests use
ActionThread
in this manner, so you could look there for various examples.