我的单元测试有一个帮助类,它共享对内存中COM对象的引用:
public class UnitTestGeometryProvider
{
public static readonly IGeometry Geometry = Deserialize();
}
从Xml文件反序列化几何体,该文件存储为资源文件并附加到项目中。然后它被包装到COM对象中:
public static IGeometry Deserialize()
{
return (IGeometry) new XMLSerializerClass().LoadFromString(myXDoc.OuterXml, null, null);
}
现在我有两个使用此类中存储的几何的测试方法:
[TestClass()]
public class MyTest
{
[TestMethod()]
public void FirstTest()
{
var p = UnitTestGeometryProvider.Geometry;
}
[TestMethod()]
public void SecondTest()
{
var p = UnitTestGeometryProvider.Geometry;
}
}
当运行第二个时,我得到一个COMException:
无法使用已与其基础RCW分离的COM对象
我想知道为什么COM-object的引用在static
中标记为UnitTestGeometryProvider
时被释放,我没有明确地释放它。所以即使如果 托管资源到实例将超出范围(这不是静态),底层COM对象应该只在我所有的时候消失当应用程序终止时,测试是否已完成或更通用,或者我是否遗漏了任何内容?
我正在使用ArcObjects和Visual NUnit。
答案 0 :(得分:0)
由于Hans Passant的评论,我发现了实际问题。
显然,Visual-NUnit-Framework决定为每个测试创建一个单独的线程。因此,每当我创建一个COM对象 - 无论是静态还是非 - 时,该对象都存在于这个单独的线程中,不能在另一个线程中使用。如果线程死也会执行COM对象或更准确地引用它。这导致GC开始抛弃COM对象,因为在该线程中不存在对它的管理引用。
解决方案非常简单:我将静态字段更改为instance-members,并在我的测试类中创建了类型为UnitTestGeometryProvider
的实例成员。因此,每个测试都会生成一个新的提供者
然而,这个解决方案非常烦人,因为必须初始化Geometry
- 属性,因此Deserialize
- 方法为每个测试运行,而不是仅对所有测试运行一次。
我不知道是否存在一个线程安全的解决方案,当初始化它的第一个线程死亡时,不会终止对COM对象的引用。