Multi-threaded unit testing
I once said that “Multithreading does a lot of things, but I don’t think ‘simplification’ is ever one of them“. Even with the simplest, most beginner level of no-frills threading, I find this to be true.
As an example, I was writing unit tests for my MonoDroid app that I recently decided to refactor with the MVP pattern (so I could increase test coverage). There’s only one place in the whole app where I use multiple threads. When the user clicks on a portfolio, there’s a web service call to get the latest stock prices (and volume, and other stock information). Because this can take a while, I want to show the user a nice animated “please wait” dialog on the UI while the web service (and other stuff) runs on a background thread. That all works great, and provides a preferable user experience to a blank screen doing nothing. (Note that I tried doing this without threads and I couldn’t get it to work–this could be a failure on my part).
However, when I got to the part where I’m testing the presenter’s orchestration of the above multi-threaded scenario, my tests started getting inconsistent results. I had also started using MSpec and JustMock at this time, and so I immediately assumed I was using those tools wrong. However, I should have immediately known it was a race condition, because sometimes my tests would all pass, and sometimes they wouldn’t. Seems obvious in retrospect.
What would happen is that sometimes my background thread would finish before the test assertions, and sometimes it wouldn’t. It was a huge relief once I figured that out, but now I have another problem: how do I test it?
My solution seems a little hacky, but it works. I was reminded of stories of people who wanted to test what would happen to certain parts of code at different times of the day. I.e. service X should do one thing in the morning, and another thing in the evening. But you can’t really inject a mock into every place the DateTime class is used. So, one approach is to simply wrap it in a service and put it behind an interface. And that’s exactly what I did with my threading code (which is a PostSharp aspect):
Then, when testing, before I do anything else, I set the ThreadingService to be some service that just runs the callback on the main thread, instead of putting it into a worker thread. Like so:
Since my unit tests don’t care about user experience (or even touch the UI implemention), I can now test that the presenter is doing what it’s supposed to. Is this a good general strategy for unit testing threaded code? Probably not. But maybe!
You could also use a ManualResetEvent to block the main thread while the UI thread is working. Once it’s done it can flag the MRE to stop blocking. The MRE accepts a timeout to the wait. You’re on a big PostSharp kick, so maybe that works just fine for you
Martin Fowler with an excellent article on testing non-deterministic code: http://martinfowler.com/articles/nonDeterminism.html
I am glad to see you have still been playing with MonoDroid and PostSharp.
I am on a fresh install of Windows, I installed the trial from Xamarin for MonoDroid, I decided to give MonoDevelop a try, and lastly wanted PostSharp to work with it all.
I had read your post on the SharpCrafters forum about using PostSharp with Monodroid and eventually found my way to your other blog post about PostSharp for MonoDroid (http://mgroves.com/monodroid-with-postsharp/), it really came in handy. Thanks!
On a related note, I was wondering what you ended up doing for DI/IoC with MonoDroid?
On an unrelated note, I never ended up seeing any of your code from your Project Euler framework that you had talked about at Grand Rapids Day of .NET, which was before I knew of your badassery so I didn’t go to the talk. The reason why I am bringing this up is because lately I have been solving some problems on http://codeeval.com and it reminds of of Project Euler problems.