通过 RequestComAddInAutomationService 在 C# .NET 中进行 VSTO 单元测试 Office 加载项
VSTO Unit Testing Office AddIn in C# .NET via RequestComAddInAutomationService
在过去的几周里,我研究并阅读了各种 Whosebug 问题以及其他教程和文档(N.B。其中一些在下面),试图找到一种对 VSTO 插件进行单元测试的方法。
不幸的是,它总是在我的测试中导致 E_NOINTERFACE
异常。
我正在使用的代码如下 - ThisAddin 部分 class 的一个摘录覆盖了 RequestComAddinAutomationService
,另一个描述了测试实用程序接口、测试本身,以及一个额外的程序集摘录证明 AddIn 程序集及其内部结构对测试可见。
My question is: why is this not working? I am pretty sure that this follows the generally accepted practices of VSTO testing.
如果以下不再可行,应该如何测试 VSTO? .NET remoting/IPC 是唯一的解决方案吗?
ThisAddin.cs
public partial class ThisAddin
{
#region Testing Utilities
private AddinHelper _comAddinObject;
protected override object RequestComAddInAutomationService()
{
// This is being called when I debug/run my project, but not when I run the tests
return _comAddinObject ?? (_comAddinObject = new AddinHelper());
}
#endregion
}
#region Testing Utilities
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IAddinHelper
{
Presentation GetPresentation();
string GetString();
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IAddinHelper))]
public class AddinHelper : StandardOleMarshalObject, IAddinHelper
{
public Presentation GetPresentation()
{
return Globals.ThisAddin... [...];
}
public string GetString()
{
return "Hello World!";
}
}
#endregion
AssemblyInfo.cs
[assembly: InternalsVisibleTo("MyProject.Tests")]
MyUnitTest.cs(参考了MyProject
)
[TestClass]
public class BasicTest
{
[TestMethod]
public void TestInstantiates()
{
var application = new Application();
var doc = application.Presentations.Open(@"C:\Presentation.pptx",
MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoFalse);
var comAddins = application.COMAddIns;
var comAddin = comAddins.Item("MyProject"); // Returns okay
var comObject = (IAddinHelper) comAddin.Object; // Exception occurs
Assert.AreEqual(true, true); // Never reached
doc.Close();
}
}
此外,项目的设置设置为 "Register for COM interop" 并且 Visual Studio 运行时没有错误 - 运行 它作为非管理员导致 DLL 未被注册;因此,我也知道 COM 对象 是 注册的。
产生异常
An exception of type 'System.InvalidCastException' occurred in MyProject.Tests.dll but was not handled in user code
Additional information: Unable to cast COM object of type 'System.__ComObject' to interface type 'MyProject.IAddinHelper'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{59977378-CC79-3B27-9093-82CD7A05CF74}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
计算器溢出
- VSTO Add-ins, COMAddIns and RequestComAddInAutomationService(
Register for COM Interop
没有任何改变)
- Why cannot I cast my COM object to the interface it implements in C#?(问题可能与 STAThread 无关)
- https://sqa.stackexchange.com/questions/2545/how-do-i-unit-test-word-addin-written-in-c
微软
- https://blogs.msdn.microsoft.com/varsha/2010/08/17/writing-automated-test-cases-for-vsto-application/ <-- 即使有了这个可以正常工作的示例项目,我也得到了完全相同的错误。
- https://msdn.microsoft.com/en-us/library/bb608621.aspx
- 一般工作流程背景:https://msdn.microsoft.com/en-us/library/bb386298.aspx
老实说,我不知道如何在没有此功能的情况下测试 VSTO 加载项。
解决方案
要测试方法的项目必须通过 .Net 参考 选项卡使用 PIA Microsoft.Office.Interop.PowerPoint。
在单元测试项目中,您必须通过 COM 引用 选项卡使用 Microsoft Powerpoint 1X.0 对象库 - 它是一个 ActiveX。
令人困惑的是在解决方案资源管理器中它们都被称为:Microsoft.Office.Interop.Powerpoint
当您指定正确的引用时,您会在发生异常的行上看到此错误:
Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create'
要解决这个问题,只需在单元测试项目中添加对 Microsoft.CSharp.dll 的 .Net 引用。
接下来我们将 运行 解决您看到的错误。
首先给界面添加一个唯一的GUID & class(这样可以克服错误):
[ComVisible(true)]
[Guid("B523844E-1A41-4118-A0F0-FDFA7BCD77C9")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IAddinHelper
{
string GetPresentation();
string GetString();
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[Guid("A523844E-1A41-4118-A0F0-FDFA7BCD77C9")]
[ComSourceInterfaces(typeof(IAddinHelper))]
public class AddinHelper : StandardOleMarshalObject, IAddinHelper
其次在范围 中临时创建 private AddinHelper _comAddinObject;
public(您可以稍后在其工作时执行您的 [assembly: InternalsVisibleTo("MyProject.Tests")]).
第三,检查 Powerpoint 是否禁用了 COM 加载项。这有时会悄无声息地发生,没有 Office 应用程序的抱怨。
最后,确保勾选“为 COM 注册”。
中提琴:
参考: 几年前,我竭尽全力帮助这位 SO'r:Moq & Interop Types: works in VS2012, fails in VS2010?
在过去的几周里,我研究并阅读了各种 Whosebug 问题以及其他教程和文档(N.B。其中一些在下面),试图找到一种对 VSTO 插件进行单元测试的方法。
不幸的是,它总是在我的测试中导致 E_NOINTERFACE
异常。
我正在使用的代码如下 - ThisAddin 部分 class 的一个摘录覆盖了 RequestComAddinAutomationService
,另一个描述了测试实用程序接口、测试本身,以及一个额外的程序集摘录证明 AddIn 程序集及其内部结构对测试可见。
My question is: why is this not working? I am pretty sure that this follows the generally accepted practices of VSTO testing.
如果以下不再可行,应该如何测试 VSTO? .NET remoting/IPC 是唯一的解决方案吗?
ThisAddin.cs
public partial class ThisAddin
{
#region Testing Utilities
private AddinHelper _comAddinObject;
protected override object RequestComAddInAutomationService()
{
// This is being called when I debug/run my project, but not when I run the tests
return _comAddinObject ?? (_comAddinObject = new AddinHelper());
}
#endregion
}
#region Testing Utilities
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IAddinHelper
{
Presentation GetPresentation();
string GetString();
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IAddinHelper))]
public class AddinHelper : StandardOleMarshalObject, IAddinHelper
{
public Presentation GetPresentation()
{
return Globals.ThisAddin... [...];
}
public string GetString()
{
return "Hello World!";
}
}
#endregion
AssemblyInfo.cs
[assembly: InternalsVisibleTo("MyProject.Tests")]
MyUnitTest.cs(参考了MyProject
)
[TestClass]
public class BasicTest
{
[TestMethod]
public void TestInstantiates()
{
var application = new Application();
var doc = application.Presentations.Open(@"C:\Presentation.pptx",
MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoFalse);
var comAddins = application.COMAddIns;
var comAddin = comAddins.Item("MyProject"); // Returns okay
var comObject = (IAddinHelper) comAddin.Object; // Exception occurs
Assert.AreEqual(true, true); // Never reached
doc.Close();
}
}
此外,项目的设置设置为 "Register for COM interop" 并且 Visual Studio 运行时没有错误 - 运行 它作为非管理员导致 DLL 未被注册;因此,我也知道 COM 对象 是 注册的。
产生异常
An exception of type 'System.InvalidCastException' occurred in MyProject.Tests.dll but was not handled in user code Additional information: Unable to cast COM object of type 'System.__ComObject' to interface type 'MyProject.IAddinHelper'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{59977378-CC79-3B27-9093-82CD7A05CF74}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
计算器溢出
- VSTO Add-ins, COMAddIns and RequestComAddInAutomationService(
Register for COM Interop
没有任何改变) - Why cannot I cast my COM object to the interface it implements in C#?(问题可能与 STAThread 无关)
- https://sqa.stackexchange.com/questions/2545/how-do-i-unit-test-word-addin-written-in-c
微软
- https://blogs.msdn.microsoft.com/varsha/2010/08/17/writing-automated-test-cases-for-vsto-application/ <-- 即使有了这个可以正常工作的示例项目,我也得到了完全相同的错误。
- https://msdn.microsoft.com/en-us/library/bb608621.aspx
- 一般工作流程背景:https://msdn.microsoft.com/en-us/library/bb386298.aspx
老实说,我不知道如何在没有此功能的情况下测试 VSTO 加载项。
解决方案
要测试方法的项目必须通过 .Net 参考 选项卡使用 PIA Microsoft.Office.Interop.PowerPoint。
在单元测试项目中,您必须通过 COM 引用 选项卡使用 Microsoft Powerpoint 1X.0 对象库 - 它是一个 ActiveX。
令人困惑的是在解决方案资源管理器中它们都被称为:Microsoft.Office.Interop.Powerpoint
当您指定正确的引用时,您会在发生异常的行上看到此错误:
Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create'
要解决这个问题,只需在单元测试项目中添加对 Microsoft.CSharp.dll 的 .Net 引用。
接下来我们将 运行 解决您看到的错误。
首先给界面添加一个唯一的GUID & class(这样可以克服错误):
[ComVisible(true)]
[Guid("B523844E-1A41-4118-A0F0-FDFA7BCD77C9")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IAddinHelper
{
string GetPresentation();
string GetString();
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[Guid("A523844E-1A41-4118-A0F0-FDFA7BCD77C9")]
[ComSourceInterfaces(typeof(IAddinHelper))]
public class AddinHelper : StandardOleMarshalObject, IAddinHelper
其次在范围 中临时创建 private AddinHelper _comAddinObject;
public(您可以稍后在其工作时执行您的 [assembly: InternalsVisibleTo("MyProject.Tests")]).
第三,检查 Powerpoint 是否禁用了 COM 加载项。这有时会悄无声息地发生,没有 Office 应用程序的抱怨。
最后,确保勾选“为 COM 注册”。
中提琴:
参考: 几年前,我竭尽全力帮助这位 SO'r:Moq & Interop Types: works in VS2012, fails in VS2010?