【问题标题】:VSTO Unit Testing Office AddIn in C# .NET via RequestComAddInAutomationService通过 RequestComAddInAutomationService 在 C# .NET 中的 VSTO 单元测试办公室插件
【发布时间】:2017-12-20 15:25:27
【问题描述】:

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

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

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

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

如果无法再进行以下操作,应该如何测试 VSTO? .NET 远程处理/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 对象注册。

产生的异常

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

堆栈溢出

微软

老实说,我不知道如果没有此功能,应该如何测试 VSTO 加载项。

【问题讨论】:

  • 这个答案可能会有所帮助:https://stackoverflow.com/a/16943296/2592875
  • 感谢您的链接 - 我之前确实遇到过它,不幸的是,STAThread 属性没有产生任何结果。不过,感谢您的参与!

标签: c# testing com vsto office-interop


【解决方案1】:

解决方案

带有待测试方法的项目必须通过 .Net 参考 选项卡使用 PIA Microsoft.Office.Interop.PowerPoint。

在单元测试项目中,您必须通过 COM 参考 选项卡使用 Microsoft Powerpoint 1X.0 对象库 - 它是一个 ActiveX。

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


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

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

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


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

首先向接口&类添加一个唯一的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 应用程序不会抱怨。

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

中提琴:


参考: 几年前,我为帮助这个 SO'r 的同胞而努力工作:Moq & Interop Types: works in VS2012, fails in VS2010?

【讨论】:

  • 杰里米,你成就了我的一周!非常感谢——这很有魅力,我现在的幸福程度是无法言喻的。我也是,一直在拉头发,离开了一段时间,然后又开始为它着迷。再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-25
  • 1970-01-01
  • 2021-09-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多