简体   繁体   English

VSTO单元测试Office通过RequestComAddInAutomationService在C#.NET中添加

[英]VSTO Unit Testing Office AddIn in C# .NET via RequestComAddInAutomationService

I have worked and read through various StackOverflow questions and other tutorials and documentation over the past weeks (NB some of them below) to try and find a way of unit testing a VSTO AddIn. 在过去的几周里,我一直在阅读各种StackOverflow问题和其他教程和文档(请参阅下面的一些内容),试图找到一种单元测试VSTO AddIn的方法。

Unfortunately, it always results in an E_NOINTERFACE exception in my tests. 不幸的是,它总是在我的测试中导致E_NOINTERFACE异常。

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. 我使用的代码是下面-内的ThisAddIn局部类中重写的一种提取物RequestComAddinAutomationService ,另一个描述测试实用程序接口,测试本身,以及另外的组件提取物证明外接程序组件和它的内部是可见的测试。

My question is : why is this not working? 我的问题是 :为什么这不起作用? I am pretty sure that this follows the generally accepted practices of VSTO testing. 我很确定这遵循VSTO测试的普遍接受的做法。

If the below is not possible anymore, how should one go about testing VSTO? 如果以下不再可能,那么应该如何测试VSTO? Is .NET remoting/IPC the only solution? .NET远程处理/ IPC是唯一的解决方案吗?

ThisAddin.cs 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 AssemblyInfo.cs中

[assembly: InternalsVisibleTo("MyProject.Tests")]

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

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; 此外,项目的设置设置为“注册COM互操作”并且Visual Studio运行升级而没有错误 - 将其作为非管理员运行导致DLL未注册; therefore, I also know that the COM objects are registered. 因此,我也知道COM对象注册。

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'. MyProject.Tests.dll中出现“System.InvalidCastException”类型的异常但未在用户代码中处理附加信息:无法将“System .__ ComObject”类型的COM对象强制转换为接口类型“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)). 此操作失败,因为对于具有IID“{59977378-CC79-3B27-9093-82CD7A05CF74}”的接口的COM组件的QueryInterface调用由于以下错误而失败:不支持此类接口(HRESULT异常:0x80004002(E_NOINTERFACE)) 。

StackOverflow 堆栈溢出

Microsoft 微软

I honestly don't know how one is supposed to test VSTO Add-Ins without this working. 老实说,我不知道在没有这个工作的情况下应该如何测试VSTO加载项。

Solution

The Project with methods to be Tested has to use the PIA Microsoft.Office.Interop.PowerPoint via the .Net reference tab. 具有待测试方法的项目必须通过.Net参考选项卡使用PIA Microsoft.Office.Interop.PowerPoint。

In the Unit Test Project you have to use the Microsoft Powerpoint 1X.0 Object Library via the COM reference tab - its an ActiveX. 在单元测试项目中,您必须通过COM参考选项卡使用Microsoft Powerpoint 1X.0对象库 - 它是一个ActiveX。

在此输入图像描述

The confusing thing is in Solution Explorer they are both called: Microsoft.Office.Interop.Powerpoint 令人困惑的是,在解决方案资源管理器中,它们都被称为: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' 缺少编译器需要成员'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create'

To solve that simply add a .Net reference to the Microsoft.CSharp.dll in the Unit Test project. 要解决此问题,只需在单元测试项目中向Microsoft.CSharp.dll添加.Net引用即可。


Next we will run into the error you're seeing. 接下来我们将遇到你所看到的错误。

Firstly add a unique GUID to the Interface & class (this will overcome the error): 首先向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

Secondly temporarily make the private AddinHelper _comAddinObject; 其次暂时使private AddinHelper _comAddinObject; public in Scope (you can do your [assembly: InternalsVisibleTo("MyProject.Tests")] later when its working) . 在Scope中公开(你可以在以后工作时使用[assembly:InternalsVisibleTo(“MyProject.Tests”)]

Thirdly, check that Powerpoint has not disabled the COM add-in. 第三,检查Powerpoint是否未禁用COM加载项。 This sometimes happens silently, without the Office App complaining. 这有时会在没有Office App抱怨的情况下默默地发生。

在此输入图像描述

Lastly, make sure Register for COM is ticked. 最后,确保勾选注册COM。

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? 参考:几年前我把头发拉出来帮助这个家伙了解: Moq和Interop类型:在VS2012中工作,在VS2010中失败了吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM