views:

92

answers:

4

I'm running my unit tests on a piece of code that does the following in the test:

Assert.IsNotNull(target.Icon);

Inside the getter for the Icon property, I'm doing this:

System.Windows.Controls.Image img = new System.Windows.Controls.Image();

That's throwing this exception: System.InvalidOperationException : The calling thread must be STA, because many UI components require this.

I understand what that means, and I understand that I need to use the Dispatcher, but I'm a bit confused about how or why... this is a property of my ViewModel and I don't get any of these exceptions when running the application.

Other info: this only started failing when I upgraded to .NET 4.

A: 

Are you using any other Non-UI thread? If so, are you sure that they don't access this property? Check if you're using any components in the framework that uses thread or runs asynchronously (like FileSystemWatcher) which may use this property. However some more code would help.

Veer
+1  A: 

The thread running the unit test is not an STA thread,you create an STA thread like that:

Thread backgroundThread;
backgroundThread = new Thread(DoWork);
backgroundThread.SetApartmentState(ApartmentState.STA);
backgroundThread.Start();

I don't know what unit testing framework you are using and how to change it's threading model but you need to somehow call Thread.SetApartmentState before Thread.Start for this to work.

The "apartment state" is a COM thing, it is required by WPF because (as the error say) many WPF controls require COM, an STA thread does not automatically have a dispatcher associated with it.

Usually you don't need to worry about the dispatcher, the system will create one if needed.

In case you do need to create a dispatcher for the thread you can just read Dispacher.CurrentDispacher - but you will not be able to do anything meaningful with that dispatcher unless you let it control the thread (by calling Dispacher.Run).

Nir
+1  A: 

The problem here is that you are unit testing WPF which requires an STA to run properly but the unit testing framework is using an MTA. You need to setup your unit testing framework to run your tests in an STA.

Each framework has a different way of doing it. Usually you can find it by just typing the testing framework name and STA into google.

JaredPar
Yep, that did it (I was using NUnit, so perfect!)
Scott Whitlock
A: 

Hi Scott, I think that you might need to change your approach a little. What I think you will need to do is modify your ViewModel so that you are exposing the URI of the image, rather than an Image control.

In your unit test you'll be able to validate that the image source will be set to the correct location, and in your UI, you'll just need to databind the source of an Image control to the URI.

Mike Goatly
Ideally, yes, but in this case my ViewModel dynamically generates an image object from two different BitMaps depending on certain properties. It's not hard coded to a URL.
Scott Whitlock