As part of the migration of my app to .NET 4, I'm struggling to get some of the WPF unit tests working again with TeamCity.
On all the tests that are somehow using a WPF control (a ListItem for example), I get an exception I didn't get before:
System.InvalidOperationException: The calling thread must be STA, because many UI components require this.
I understand what it means, and after checking, it turns out that my thread is indeed MTA, not STA.
My problem is that I have no idea on how to fix this, and where this problem could be coming from... Is it a setting on TeamCity? MSpec? Again, it worked before I switched to .NET 4.
I tried many different solutions, but nothing worked.
I'm also a bit puzzled by the fact that no-one reported this before (with my specific stack of TeamCity + MSpec + WPF test), which might mean I'm doing something very wrong somewhere.
If you have a clue, please let me know!
Full exception:
System.InvalidOperationException: The calling thread must be STA, because many UI components require this.
at System.Windows.Input.InputManager..ctor()
at System.Windows.Input.InputManager.GetCurrentInputManagerImpl()
at System.Windows.Input.KeyboardNavigation..ctor()
at System.Windows.FrameworkElement.EnsureFrameworkServices()
at System.Windows.FrameworkElement..ctor()
at System.Windows.Controls.Control..ctor()
at MyCompany.Dashboard.Client.Plugins.Common.Controls.Grids.CashflowGrid.ViewModel.ConfigureViewModel.CreateItem(String name) in d:\Program Files\JetBrains\BuildAgent2\work\6dd9af6ae2f9bbb9\Code\Src\MyCompany\Dashboard\Client\Plugins\Common\Controls\Grids\CashflowGrid\ViewModel\ConfigureViewModel.cs:line 171
at MyCompany.Dashboard.Client.Plugins.Common.Controls.Grids.CashflowGrid.ViewModel.ConfigureViewModel.Initialise(Type type, IList`1 currentSelection, Action`1 selectionChangedCallback) in d:\Program Files\JetBrains\BuildAgent2\work\6dd9af6ae2f9bbb9\Code\Src\MyCompany\Dashboard\Client\Plugins\Common\Controls\Grids\CashflowGrid\ViewModel\ConfigureViewModel.cs:line 37
at UnitTests.Plugins.Common.Controls.Grids.CashflowGrid.ViewModel.when_some_items_are_selected_on_the_chosen_list.<.ctor>b__1() in d:\Program Files\JetBrains\BuildAgent2\work\6dd9af6ae2f9bbb9\Code\Src\UnitTests.Plugins.Common\Controls\Grids\CashflowGrid\ViewModel\ConfigureViewModelTests.cs:line 82
For this exception, the code is simply trying to instantiate a ListBoxItem, nothing fancy, but doing that on a MTA thread breaks it.
What I tried:
Setting the current thread to STA
Thread.CurrentThread.SetApartmentState(ApartmentState.STA)
It of course doesn't work because it's only possible before the thread starts
Run the code in a separate thread that was initialised as STA: very complex since, due to the nature of MSpec, different methods are called at different time so you can't run EVERYTHING under the same thread. More precisely, you can't run the "Establish context" on the same thread as the "Because of" statement.
Use the STAThread attribute... yes but where? never worked anywhere I tried
Example of a failing test:
public class StaTestExample
{
Establish context = () => _control = new ListBox();
It should_not_be_null = () => _control.ShouldNotBeNull();
protected static Control _control;
}
It now works.
But the problem is we just can't explain it. And it still fails on a different build server, but we don't care about this one.
In case someone gets that problem, here what we did:
The odd thing is that exact process was applied on a different build server (an old one we don't use anymore), and it still fails.
There's nothing else we could think of that changed.
So it's a bit of a mystery... I hope it won't come back to bite us!