为什么关闭在单元测试中创建的窗口会引发InvalidComObjectException
本文关键字:窗口 InvalidComObjectException 创建 单元测试 为什么 | 更新日期: 2023-09-27 18:19:06
在使用MSTest进行单元测试时,我创建了一个WPF窗口。当这个窗口关闭时,Visual Studio显示InvalidComObjectException
:
COM object that has been separated from its underlying RCW cannot be used.
在 [TestMethod]
退出后引发,并且堆栈只包含外部代码(不包含InnerException
)。这是我的文件:
StackTrace:
at System.Windows.Input.TextServicesContext.StopTransitoryExtension()
at System.Windows.Input.TextServicesContext.Uninitialize(Boolean appDomainShutdown)
at System.Windows.Input.TextServicesContext.TextServicesContextShutDownListener.OnShutDown(Object target, Object sender, EventArgs e)
at MS.Internal.ShutDownListener.HandleShutDown(Object sender, EventArgs e)
DeclaringType:
{Name = "TextServicesContext" FullName = "System.Windows.Input.TextServicesContext"}
Assembly:
{PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35}
下面是创建窗口的代码:
var myWindow = new SomeWindow(errors);
myWindow.ShowDialog();
窗口包含两个ListView
,其中包含一些文本元素和复选框
我是前段时间偶然发现的。如果我没记错的话,这是因为在测试之间,AppDomain的默认Dispatcher没有被正确地清理和重新初始化。
为了解决这个问题,我创建了一个DomainNeedsDispatcherCleanup
属性类,它负责Dispatcher的正确设置和拆卸。我一找到它就把它包含在这里,但请注意,我使用的是XUnit,而不是MSTest。
编辑:刚刚找到。给你:
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Threading;
using Xunit;
namespace Boost.Utils.Testing.XUnit.WPF
{
/// <summary>helful if you stumble upon 'object disconnected from RCW' ComException *after* the test suite finishes,
/// or if you are unable to start the test because the VS test runner tells you 'Unable to start more than one local run'
/// even if all tests seem to have finished</summary>
/// <remarks>only to be used with xUnit STA worker threads</remarks>
[AttributeUsage(AttributeTargets.Method)]
public class DomainNeedsDispatcherCleanupAttribute : BeforeAfterTestAttribute
{
public override void After(MethodInfo methodUnderTest)
{
base.After(methodUnderTest);
Dispatcher.CurrentDispatcher.InvokeShutdown();
}
}
}
哈哈. .因此,正如您所看到的,修复是微不足道的。我不记得了。当然,你只需要InvokeShutdown
在你的teardown,它应该是固定的。