【问题标题】:Why do I get an Invalid Operation Exception (non STA thread?) running this MSpec test on TeamCity?为什么在 TeamCity 上运行此 MSpec 测试时会出现无效操作异常(非 STA 线程?)?
【发布时间】:2013-03-12 14:43:08
【问题描述】:

作为将我的应用迁移到 .NET 4 的一部分,我正在努力让一些 WPF 单元测试再次与 TeamCity 一起工作。

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

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

我明白是什么意思了,查了一下发现我的线程确实是MTA,不是STA。

我的问题是我不知道如何解决这个问题,以及这个问题可能来自哪里...... 它是 TeamCity 上的设置吗?规格? 同样,它在我切换到 .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 的性质,不同的方法在不同的时间被调用,所以你不能在同一个线程下运行所有​​的东西。更准确地说,您不能在与“Because of”语句相同的线程上运行“Establish context”。

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

失败测试示例:

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

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

    protected static Control _control;
}

【问题讨论】:

  • 当您使用控制台运行程序运行您的规范时,它是否运行?如果是这样,您的问题与 TeamCity 无关。顺便说一句,mspec.exe 的 Program.Main() 归因于 [STAThread]
  • 这对于单元测试运行者来说从来都不是问题。 [STAThread] 不起作用,它只能在程序的入口点上识别。不适用于测试运行器,入口点是运行器本身,而不是测试代码。大多数测试运行者都有一个选项来指定测试线程应该是 MTA 还是 STA,我没有看到 mspec 的选项。
  • MSpec 目前仅支持 STAThread。我真的不明白你的意思,@HansPassant。规范是否使用 mspec.exe(控制台测试运行程序)运行?
  • 其实是个好问题。它与 Resharper 运行器和 NCrunch 运行器一起工作没有问题,但没有尝试在本地使用 mspec.exe 手动运行它。让我马上试试,然后回复你
  • 好的,所以我使用我在 TeamCity 端使用的相同 mspec-clr4.exe 手动运行了测试,它在本地运行良好,但在 TeamCity 上失败了。所以肯定跟 TeamCity 有关系吧?

标签: .net-4.0 teamcity mspec sta


【解决方案1】:

现在可以了。

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

如果有人遇到这个问题,我们做了什么:

  • 禁用测试覆盖率
  • 禁用 MSPec 任务:构建变为绿色
  • 重新启用覆盖和 MSpec:它有效...

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

没有其他我们能想到的改变了。

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

【讨论】:

  • 如果我遇到你的情况,我会想知道我是否真的需要对线程中的东西进行单元测试。代码不能被分解,以便您可以对其进行单元测试而不必激活多个线程吗?
  • 这完全超出了我的控制范围,测试是在测试 UI 控件,线程是由框架创建的。顺便说一句,它仍然工作正常,仍然不知道最初出了什么问题。我会责怪我没有尽快牺牲一只山羊。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-26
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 2011-07-09
相关资源
最近更新 更多