尝试从资源字典访问图像资源时,多个NUnit测试类失败

Dav*_*vid 4 c# wpf nunit unit-testing

我有一个用C#(.NET 4.0)编写的复杂WPF项目,我为(NUnit)编写了几个测试.这些测试存在于不同的类中,只要我为每个类单独运行测试,一切都很好.但是,一旦我尝试同时运行所有类的所有测试,第一个类的测试就会成功,但是一旦testrunner(Resharper或nunit-console)开始测试剩余的类,所有这些类都会失败并显示以下堆栈跟踪.

System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it
at System.Windows.Threading.Dispatcher.VerifyAccess()
at System.Windows.Media.Imaging.BitmapDecoder.ToString()
at System.Windows.Media.Imaging.BitmapFrameDecode.ConvertToString(String format, IFormatProvider provider)
at System.Windows.Media.ImageSource.ToString()
at MUSTANG.ShowCase.ResourceLibrary.ResourceDictionaryManager.GetUriString(String pKey) in c:\Daten\Jenkins-ci\jobs\MUSTANG-Showcase-Release-VS2010\workspace\MUSTANG-Showcase\MUSTANG.ShowCase.ResourceLibrary\ResourceDictionaryManager.cs:Zeile 49.
Run Code Online (Sandbox Code Playgroud)

相应的代码如下:

public object GetValue(string pKey)
{
    if (mDictionary.Contains(pKey))
    {
        return mDictionary[pKey];
    }
    return null;
}

public String GetUriString(string pKey)
{
    object result = GetValue(pKey);
    if (null == result)
    {
        Log.Warn(string.Format(@"Ressource '{0}' nicht gefunden!", pKey));
        return "";
    }
    return result.ToString();
}
Run Code Online (Sandbox Code Playgroud)

当资源是图像时,GetUriString中的最后一行发生异常.Nunit似乎使用不同的线程来运行不同的测试类 - 它们仍按顺序运行.有没有办法解决这个问题,例如通过告诉NUnit或testrunners使用单个线程,在每个测试类运行后完全退出或类似?

编辑1:到目前为止我尝试过的内容:

  • [RequiresSTA]属性装饰测试
  • 在运行每个测试类之前重置ResourceDictionaryManager类(发生此错误的位置).这解决了ResourceDictionaryManager类中的问题,但是在代码中"稍后"出现完全相同的问题.
  • 将所有测试复制到同一个巨大的类中.所有测试都运行良好(但这不是我想要的)

问题似乎是NUnit为包含测试方法的每个类使用不同的线程,所以我要么找到一种方法

  • 告诉NUnit在同一个线程中运行所有测试类

要么

  • 在TestFixtureTearDown方法中告诉NUnit完全关闭应用程序,这样我就可以在下一个测试类中实例化一个新的应用程序 new Application();

Gis*_*shu 7

从堆栈跟踪,你发布它似乎你有一个'线程关联'问题 - 即你试图更新一个不同于它创建的线程上的UI元素.BitmapDecoder派生自DispatcherObject,即它需要在单个线程上运行.在您的测试运行中,它似乎是在一个线程上创建的,然后方法调用(ToString)来自不同的线程.

  • 您是否肯定您没有在代码中生成线程?NUnit AFAIK使用相同的线程在测试运行中运行所有测试.你正在运行什么版本?
  • 您是否共享相同的MUSTANG.ShowCase.ResourceLibrary跨测试实例?如何为每个测试创建一个新实例,即隔离测试?

更新:我想我已经把它钉了下来.

  • 如果测试夹具仅使用TestFixture属性标记(无线程要求),则所有测试都在单个MTA线程上运行
  • 如果您使用RequiresSTA属性标记每个TestFixture,我会看到跑步者将为每个测试夹具创建一个新的STA线程(这似乎与您报告的内容相匹配).
  • 由于您希望在同一个STA线程上进行所有测试(跨夹具),因此应在汇编级别(在AssemblyInfo.cs文件中)指定此项.您可以在每个夹具级别删除该属性.

.

[assembly: RequiresThread(ApartmentState.STA)]
Run Code Online (Sandbox Code Playgroud)