2013-03-12 50 views
2

作为我的应用程序迁移到.NET 4的一部分,我正努力让一些WPF单元测试再次与TeamCity一起工作。为什么我会在TeamCity上运行此MSpec测试时遇到无效操作异常(非STA线程?)?

在那个以某种方式使用WPF控件(例如列表项)的所有测试中,我得到一个异常之前,我并没有得到:

System.InvalidOperationException: The calling thread must be STA, because many UI components require this. 

我明白这意味着什么,并检查后,事实证明,我的线程确实是MTA,而不是STA。

我的问题是,我不知道如何解决这个问题,以及这个问题可能来自哪里...... 这是TeamCity上的一个设置吗? MSpec? 再次,它工作之前,我切换到.NET 4.

我尝试了许多不同的解决方案,但没有奏效。

我也有点困惑的事实,没有人之前报告过(与我的特定堆栈的TeamCity + MSpec + WPF测试),这可能意味着我做某事非常错误的事情。

如果您有线索,请告诉我!

完全例外:

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 

这一例外,代码只是想实例化一个ListBoxItem的,没有什么花哨,但这样做在一个MTA线程打破它。

我的尝试:

  • 当前线程设置为STA

    Thread.CurrentThread.SetApartmentState(ApartmentState.STA)

当然,因为不工作的这只有在线程启动之前才有可能

  • 在被初始化为STA的单独线程中运行代码: 非常复杂,因为由于MSpec的性质,在不同的时间调用不同的方法,所以不能在同一线程下运行EVERYTHING。更确切地说,你不能在“因为”语句的同一个线程上运行“建立上下文”。

  • 使用STAThread属性...是的,但在哪里?从来没有在任何地方工作,我 试图

    失败测试

例子:

public class StaTestExample 
{ 
    Establish context =() => _control = new ListBox(); 

    It should_not_be_null =() => _control.ShouldNotBeNull(); 

    protected static Control _control; 
} 
+0

当你用控制台运行器运行它时,你的规格是否运行?如果是这样,你的问题与TeamCity无关。顺便说一句,mspec.exe的Program.Main()被赋予了'[STAThread]'。 – 2013-03-12 16:01:19

+0

这对于单元测试运动员来说绝对不是问题。 [STAThread]不起作用,只能在程序的入口点处识别。对测试运行者不起作用,入口点是跑步者本身,而不是测试代码。大多数测试运行者可以选择指定测试线程是否应该是MTA或STA,我没有看到一个用于mspec。 – 2013-03-12 16:50:54

+0

MSpec截止目前仅支持STAThread。我真的不明白你的意思,@HansPassant。该规格是否与mspec.exe(控制台测试运行器)一起运行? – 2013-03-12 16:56:04

回答

0

现在的作品。

但问题是我们无法解释它。它仍然在一个不同的构建服务器上失败,但我们不关心这个。

万一有人得到了这个问题,在这里我们所做的事情:

  • 禁用测试覆盖率
  • 禁用MSPec任务:构建云绿
  • 重新启用覆盖和MSpec:它的工作原理。 ..

奇怪的是,确切的过程被应用在不同的构建服务器(旧的我们不再使用),它仍然失败。

没有别的可以想象的改变了。

所以这有点神秘......我希望它不会回来咬我们!

+0

如果我在你的情况,我会想知道如果我真的需要单元测试线程中的东西。不能将代码分解开来,以便您可以进行单元测试,而不必让多个线程处于活动状态? – 2013-04-10 18:08:07

+0

那么这完全超出了我的控制范围,测试是测试UI控件,线程是由框架创建的。顺便说一下,它仍然工作得很好,但仍然不知道原来出了什么问题。我会责怪我没有尽快牺牲一只山羊的事实。 – 2013-04-11 16:05:32

相关问题