views:

26

answers:

2

How do I unit testing a class which makes use of System.Windows.Threading.Dispatcher?

I am following the MVVM pattern in the setting of WPF. As part of this I am creating a DispatchingBlah class following the pattern used for DispatchingQuoteSource that I saw in this video (see 1:06:16 ish).

I want to test that my class has queued the correct things to the dispatcher object, but I'm having trouble figuring out how to do that. There is no way for me (as far as I can find) to synchronously flush out the queue in order to see the effects of the queued objects. Nor can I see how to query the queue to inspect what has been added.

Do I need to concoct some interface around the System.Windows.Threading.Dispatcher class?

+1  A: 

I'd hide the dispatcher class behind an interface, and use a mock dispatcher (or just a hand-rolled fake) for testing. That way, you can verify that the correct calls are made, without having to try to actually test the actual dispatcher.

This is, of course, assuming that you want to test the VM, and that you trust the dispatcher. Even in that case, it's probably better to test the dispatcher separately.

kyoryu
+1  A: 

Actually, there already exists a better solution than an interface around the dispatcher class. It's called SynchronizationContext. This is an abstraction of the Dispatcher idea that also works for Windows Forms (using ISynchronizeInvoke). So you also get the benifit of added reusability for your class.

The Nito.Async library has several types that are useful when doing unit testing with SynchronizationContext; it has many unit tests itself that use those classes.

Stephen Cleary
Hm, apparently it's not so easy to wrap the using System.Windows.Threading.Dispatcher in the ISynchronizeInvoke interfaces..http://geekswithblogs.net/robp/archive/2008/03/28/why-doesnt-dispatcher-implement-isynchronizeinvoke.aspx
pauldoo
That's not what I meant. `Dispatcher` is wrapped in a `SynchronizationContext` class, and `ISynchronizeInvoke` is wrapped in a (different) `SynchronizationContext` class. The abstraction is `SynchronizationContext`, not `ISynchronizeInvoke`.
Stephen Cleary
P.S. Check out my comment on that blog entry on 1/26/2009.
Stephen Cleary