【问题标题】:Using WPF components in NUnit tests - how to use STA?在 NUnit 测试中使用 WPF 组件 - 如何使用 STA?
【发布时间】:2011-01-14 07:02:20
【问题描述】:

我需要在 NUnit 单元测试中使用一些 WPF 组件。我通过 ReSharper 运行测试,使用 WPF 对象时失败并出现以下错误:

System.InvalidOperationException:

调用线程必须是 STA,因为很多 UI 组件都需要这个。

我已经阅读过这个问题,听起来线程需要是STA,但我还没有弄清楚如何做到这一点。触发问题的是以下代码:

[Test]
public void MyTest()
{
    var textBox = new TextBox(); 
    textBox.Text = "Some text"; // <-- This causes the exception.
}

【问题讨论】:

  • 这不是单元测试。另外,您确定要让您的测试依赖 WPF 组件吗?出于上述原因,UI 应与应用程序逻辑分开。
  • 嗯 - 我知道这里没有实际测试,这不是我的单元测试的样子。但是 - 这是足够的代码来说明这一点。此外 - 问题与这是通过 ReSharper 运行的 nNnit 单元测试这一事实有关 - 所以我需要保留这个问题的上下文。你的另一点是有效的。我不希望我的单元测试依赖于 WPF 组件,但现在这似乎是最好的解决方案。看看我以后能不能把它弄出来..
  • 如果您想了解为什么我在应用程序逻辑中有 UI,请参阅我的另一个问题:stackoverflow.com/questions/2220842/…
  • 在动态 UI 中,例如从 System.Windows.Interactivity.Behavior&lt;&gt; 派生的行为、WPF 扩展方法(例如 static void InsertUnder(this UIElementCollection, UIElement afterThis, UIElement toInsert))、布局管理器代码、动态数据模板和组件创作是一些示例场景,其中编写依赖于 WPF 组件的单元测试是实用的。

标签: c# wpf unit-testing nunit resharper


【解决方案1】:

随着更新的版本,属性发生了变化:

[Apartment(ApartmentState.STA)]
public class MyTestClass
{}

【讨论】:

  • 这是 NUnit > 版本 3 的当前答案。
  • 我要补充一点,您可以将属性放在各个测试函数上,以将其隔离到您实际需要的位置。如果您正在测试异步代码,而您的测试函数具有像public async Task TestFunc() 这样的签名,您可能会遇到其他问题。在 MVVM 世界中的这种情况下,您可能希望将调度程序依赖项注入您的视图模型,在内部使用它来操作视图对象,并在您的测试中同样使用它。这甚至可以消除对测试程序集、类、测试函数的Apartment 属性的需要。
  • 在使用[TestFixture, Apartment(ApartmentState.STA)] 的类或使用[Test, Apartment(ApartmentState.STA)] 的方法上声明时对我有用
  • 我使用的是 NUnit 3.2.0 版,我无法通过仅使用 [Apartment(ApartmentState.STA)] 装饰方法来完成这项工作。我不得不用属性来装饰这个类。奇怪。
【解决方案2】:

你试过this吗?


...只需为您尝试测试的 dll 创建一个 app.config 文件,并添加一些 NUnit 适当的设置以强制 NUnit 将测试环境创建为 STA 而不是 MTA。

为方便起见,这里是您需要的配置文件(或将这些部分添加到您现有的配置文件中):

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <sectionGroup name="NUnit">
            <section name="TestRunner" type="System.Configuration.NameValueSectionHandler"/>
        </sectionGroup>
    </configSections>

    <NUnit>
        <TestRunner>
            <add key="ApartmentState" value="STA" />
        </TestRunner>
    </NUnit>
</configuration> 

【讨论】:

  • 谢谢!刚刚自己找到了相同的解决方案,并且有效。显然 ReSharper 使用的是旧版本的 nUnit,因此我不能简单地使用 [RequiresSTA] 属性。
  • 如果特定版本的 ReSharper 存在 RequiresSTA 问题,那么为什么不让 ReSharper 忽略该警告?
  • 以下针对不同版本的 NUnit 提供了更好的解决方案,但未将它们标记为答案。
【解决方案3】:

您应该将RequiresSTA 属性添加到您的测试类。

[TestFixture, RequiresSTA]
public class MyTestClass
{
}

【讨论】:

  • 这仅适用于 3.0 以下的 NUnit 版本。它已过时 > 版本 3。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-13
  • 1970-01-01
  • 1970-01-01
  • 2011-10-20
  • 2015-04-19
相关资源
最近更新 更多