通过 RequestComAddInAutomationService 在 C# .NET 中的 VSTO 单元测试 Office 插件 [英] VSTO Unit Testing Office AddIn in C# .NET via RequestComAddInAutomationService

查看:15
本文介绍了通过 RequestComAddInAutomationService 在 C# .NET 中的 VSTO 单元测试 Office 插件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在过去的几周里,我研究并阅读了各种 StackOverflow 问题以及其他教程和文档(注意下面的一些),试图找到一种对 VSTO 插件进行单元测试的方法.

不幸的是,它总是在我的测试中导致 E_NOINTERFACE 异常.

我正在使用的代码如下 - ThisAddin 部分类的一个摘录覆盖 RequestComAddinAutomationService,另一个描述测试实用程序接口,测试本身,以及一个额外的程序集摘录证明AddIn 程序集及其内部对测试是可见的.

<块引用>

我的问题是:为什么这不起作用?我很确定这遵循了公认的 VSTO 测试实践.

如果无法再进行以下操作,应该如何测试 VSTO?.NET 远程处理/IPC 是唯一的解决方案吗?

ThisAddin.cs

公共部分类ThisAddin{#region 测试实用程序私人 AddinHelper _comAddinObject;受保护的覆盖对象 RequestComAddInAutomationService(){//这是在我调试/运行我的项目时调用的,但不是在我运行测试时调用的返回 _comAddinObject ??(_comAddinObject = new AddinHelper());}#endregion}#region 测试实用程序[ComVisible(真)][接口类型(ComInterfaceType.InterfaceIsDual)]公共接口 IAddinHelper{演示 GetPresentation();字符串 GetString();}[ComVisible(真)][ClassInterface(ClassInterfaceType.None)][ComSourceInterfaces(typeof(IAddinHelper))]公共类 AddinHelper : StandardOleMarshalObject, IAddinHelper{公共演示 GetPresentation(){返回 Globals.ThisAddin... [...];}公共字符串 GetString(){返回你好世界!";}}#endregion

AssemblyInfo.cs

[程序集:InternalsVisibleTo("MyProject.Tests")]

MyUnitTest.cs(引用了MyProject)

[TestClass]公共类 BasicTest{[测试方法]公共无效TestInstantiates(){var 应用程序 = 新应用程序();var doc = application.Presentations.Open(@"C:Presentation.pptx",MsoTriState.msoFalse、MsoTriState.msoFalse、MsoTriState.msoFalse);var comAddins = application.COMAddIns;var comAddin = comAddins.Item("MyProject");//正常返回var comObject = (IAddinHelper) comAddin.Object;//发生异常断言.AreEqual(true, true);//从未到达doc.Close();}}

此外,项目的设置设置为注册 COM 互操作",并且 Visual Studio 运行提升且没有错误 - 以非管理员身份运行会导致 DLL 未注册;因此,我也知道 COM 对象注册.

产生的异常

<块引用>

MyProject.Tests.dll 中出现System.InvalidCastException"类型的异常,但未在用户代码中处理附加信息:无法将System.__ComObject"类型的 COM 对象转换为接口类型MyProject.IAddinHelper".此操作失败,因为 IID 为{59977378-CC79-3B27-9093-82CD7A05CF74}"的接口的 COM 组件上的 QueryInterface 调用因以下错误而失败:不支持此类接口(HRESULT 异常:0x80004002 (E_NOINTERFACE)).

堆栈溢出

  • 令人困惑的是在解决方案资源管理器中它们都被称为:Microsoft.Office.Interop.Powerpoint

    <小时>

    当您指定正确的引用时,您将在发生异常的行上看到此错误:

    <块引用>

    缺少编译器所需的成员Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create"

    要解决这个问题,只需在单元测试项目中添加对 Microsoft.CSharp.dll 的 .Net 引用.

    <小时>

    接下来我们会遇到你看到的错误.

    首先向界面添加一个唯一的 GUID&类(这将克服错误):

    [ComVisible(true)][指南(B523844E-1A41-4118-A0F0-FDFA7BCD77C9")][接口类型(ComInterfaceType.InterfaceIsDual)]公共接口 IAddinHelper{字符串 GetPresentation();字符串 GetString();}[ComVisible(真)][ClassInterface(ClassInterfaceType.None)][指南(A523844E-1A41-4118-A0F0-FDFA7BCD77C9")][ComSourceInterfaces(typeof(IAddinHelper))]公共类 AddinHelper : StandardOleMarshalObject, IAddinHelper

    其次,暂时将 private AddinHelper _comAddinObject; 在 Scope 中公开(您可以稍后在其工作时执行您的 [assembly: InternalsVisibleTo("MyProject.Tests")]).

    第三,检查 Powerpoint 没有禁用 COM 加载项.这有时会静默发生,Office 应用程序不会抱怨.

    最后,确保注册 COM 被勾选.

    中提琴:

    <小时>

    参考: 几年前,我在帮助这个 SO'r 的人:Moq &互操作类型:在 VS2012 中有效,在 VS2010 中失败?

    I have worked and read through various StackOverflow questions and other tutorials and documentation over the past weeks (N.B. some of them below) to try and find a way of unit testing a VSTO AddIn.

    Unfortunately, it always results in an E_NOINTERFACE exception in my tests.

    The code I am using is below - one extract of the ThisAddin partial class overriding the RequestComAddinAutomationService, another describing the test utility interface, the test itself, as well as an additional assembly extract proving that the AddIn assembly and its internals are visible to the test.

    My question is: why is this not working? I am pretty sure that this follows the generally accepted practices of VSTO testing.

    If the below is not possible anymore, how should one go about testing VSTO? Is .NET remoting/IPC the only solution?

    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 (has a reference to 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();
        }
    }
    

    Furthermore, the project's settings are set to "Register for COM interop" and Visual Studio runs elevated without errors - running it as non-admin results in the DLLs not being registered; therefore, I also know that the COM objects are registered.

    Resulting Exception

    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)).

    StackOverflow

    Microsoft

    I honestly don't know how one is supposed to test VSTO Add-Ins without this working.

    解决方案

    Solution

    The Project with methods to be Tested has to use the PIA Microsoft.Office.Interop.PowerPoint via the .Net reference tab.

    In the Unit Test Project you have to use the Microsoft Powerpoint 1X.0 Object Library via the COM reference tab - its an ActiveX.

    The confusing thing is in Solution Explorer they are both called: Microsoft.Office.Interop.Powerpoint


    When you specify the correct References you'll see this error on the line where the exception occurs:

    Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create'

    To solve that simply add a .Net reference to the Microsoft.CSharp.dll in the Unit Test project.


    Next we will run into the error you're seeing.

    Firstly add a unique GUID to the Interface & class (this will overcome the error):

    [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
    

    Secondly temporarily make the private AddinHelper _comAddinObject; public in Scope (you can do your [assembly: InternalsVisibleTo("MyProject.Tests")] later when its working).

    Thirdly, check that Powerpoint has not disabled the COM add-in. This sometimes happens silently, without the Office App complaining.

    Lastly, make sure Register for COM is ticked.

    Viola:


    Ref: I pulled my hair out working this out years ago helping this fellow SO'r: Moq & Interop Types: works in VS2012, fails in VS2010?

    这篇关于通过 RequestComAddInAutomationService 在 C# .NET 中的 VSTO 单元测试 Office 插件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆