VSTOunit testing通过RequestComAddInAutomationService在C#.NET中添加Office
在过去的几周里,我一直在阅读各种StackOverflow问题和其他教程和文档(下面注意其中一些),试图找到一种unit testingVSTO AddIn的方法。
不幸的是,它总是在我的测试中导致E_NOINTERFACE
exception。
我正在使用的代码如下 – 覆盖RequestComAddinAutomationService的ThisAddin部分类的一个提取,另一个描述测试实用程序接口的提取,测试本身,以及另一个程序集提取,certificateAddIn程序集及其内部对测试可见。
我的问题是 :为什么这不起作用? 我很确定这遵循VSTO测试的普遍接受的做法。
如果以下不再可能,那么应该如何测试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(); } }
此外,项目的设置设置为“注册COM互操作”并且Visual Studio运行升级而没有错误 – 将其作为非管理员运行导致DLL未注册; 因此,我也知道COM对象已注册。
结果exception
MyProject.Tests.dll中出现“System.InvalidCastException”类型的exception但未在用户代码中处理附加信息:无法将“System .__ ComObject”类型的COM对象强制转换为接口类型“MyProject.IAddinHelper”。 此操作失败,因为对于具有IID“{59977378-CC79-3B27-9093-82CD7A05CF74}”的接口的COM组件的QueryInterface调用由于以下错误而失败:不支持此类接口(HRESULTexception:0x80004002(E_NOINTERFACE)) 。
堆栈溢出
- 如何从其他c#项目中调用VSTO类
- unit testingVSTO项目
- VSTO加载项,COMAddIns和RequestComAddInAutomationService (
Register for COM Interop
不会改变任何内容) - 为什么我不能将我的COM对象转换为它在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。
在unit testing项目中,您必须通过COM参考选项卡使用Microsoft Powerpoint 1X.0对象库 – 它是一个ActiveX。
令人困惑的是在解决方案资源管理器中,它们都被称为:Microsoft.Office.Interop.Powerpoint
指定正确的引用时,您将在发生exception的行上看到此错误:
缺少编译器需要成员’Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create’
要解决此问题,只需在unit testing项目中向Microsoft.CSharp.dll添加.Net引用即可。
接下来我们将遇到您所看到的错误。
首先向Interface &class添加一个唯一的GUID(这将克服错误):
[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;
在Scope中公开(你可以在以后工作时使用[assembly:InternalsVisibleTo(“MyProject.Tests”)] 。
第三,检查Powerpoint是否未禁用COM加载项。 这有时会在没有Office App抱怨的情况下默默地发生。
最后,确保勾选注册COM。
中提琴:
参考:几年前我把头发拉出来帮助这个家伙: Moq和Interop类型:在VS2012中工作,在VS2010中失败了吗?
- 使用在Windows上配置的DSN连接ODBC(无用户名和密码)
- AppDomain.CurrentDomain.AssemblyResolve in dynamics crm
- ASP.NET PostBack选择treeview的复选框
- C#:创建一个安装WPF应用程序(ClickOnce)和Windows服务的安装程序
- 在PDF上添加签名图像,而无需使用iTextSharp对其进行数字签名
- 在Visual Inheritance的情况下,事件处理的标准方法是什么?
- Interlocked.CompareExchange 使用GreaterThan或LessThan而不是相等
- selenium webdriver管理速度?
- 在文本文件的顶部添加一行