vb.net - Microsoft Office .NET 插件的单元测试

标签 vb.net ms-office add-in

有人对 Office 托管应用程序加载项的单元测试有任何建议吗?我正在使用 NUnit,但我在使用 MSTest 时遇到了同样的问题。

问题是 Office 应用程序(在我的例子中为 Word)内加载了一个 .NET 程序集,并且我需要对该 .NET 程序集的该实例的引用。我不能只实例化该对象,因为这样它就没有 Word 实例来执行操作。

现在,我可以使用 Application.COMAddIns("Name of addin").Object 接口(interface)来获取引用,但这会获取通过 RequestComAddInAutomationService 返回的 COM 对象。到目前为止,我的解决方案是让该对象为我想要测试的真实 .NET 对象中的每个方法都拥有代理方法(所有这些方法都在条件编译下设置,以便它们在发布的版本中消失)。

COM 对象(VB.NET 类)实际上具有对真实加载项实例的引用,但我尝试将其返回到 NUnit,结果出现了一个不错的 p/Invoke 错误:

System.Runtime.Remoting.RemotingException:此远程处理代理没有 channel 接收器,这意味着服务器没有正在监听的注册服务器 channel ,或者此应用程序没有合适的客户端 channel 与服务器通信。 在System.Runtime.Remoting.Proxies.RemotingProxy.InternalInvoke(IMethodCallMessage reqMcmMsg, bool useDispatchMessage,Int32 callType) 在 System.Runtime.Remoting.Proxies.RemotingProxy.Invoke(IMessage reqMsg) 在System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&msgData,Int32类型)

我尝试使主加载项 COM 可见,但错误发生了变化:

System.InvalidOperationException:由于对象的当前状态,操作无效。 在 System.RuntimeType.ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)

虽然我有一个解决方法,但它很困惑,并且将大量测试代码放入实际项目而不是测试项目中 - 这并不是 NUnit 真正的工作方式。

最佳答案

我就是这样解决的。

  1. 我的加载项中的几乎所有内容都通过 UI 中按钮的 Click 方法运行。我已将所有这些 Click 方法更改为仅包含简单的无参数调用。

  2. 然后,我创建了一个名为 EntryPoint 的新文件(部分类),其中包含许多非常短的 Friend Sub,其中每个通常都是对参数化工作函数的一到两次调用,以便所有 Click 方法都被调用到这个文件。例如,有一个函数可以打开标准文档并调用“另存为”到我们的 DMS 中。该函数接受一个要打开哪个文档的参数,我们使用了几十个标准文档。

所以我有

Private Sub btnMemo_Click(ByVal Ctrl As Microsoft.Office.Core.CommandBarButton, ByRef CancelDefault As Boolean) Handles btnMemo.Click
    DocMemo()
End Sub

在 ThisAddin 中,然后

Friend Sub DocMemo()
    OpenDocByNumber("Prec", 8862, 1)
End Sub

在我的新 EntryPoints 文件中。

  • 我添加了一个新的 AddInUtilities 文件,其中包含

    公共(public)接口(interface)IAddInUtilities

  • #如果调试则

    Sub DocMemo()
    

    #End If

    End Interface
    
    
    Public Class AddInUtilities
        Implements IAddInUtilities
        Private Addin as ThisAddIn
    

    #如果调试则

    Public Sub DocMemo() Implements IAddInUtilities.DocMemo
        Addin.DocMemo()
    End Sub
    

    #End If

     Friend Sub New(ByRef theAddin as ThisAddIn)
         Addin=theAddin
     End Sub
     End Class
    
  • 我转到 ThisAddIn 文件并添加

    私有(private)实用程序作为 AddInUtilities

    protected 重写函数 RequestComAddInAutomationService() 作为对象 如果公用事业什么都不是那么 实用程序 = 新的 AddInUtilities(Me) 万一 返回公用事业 结束函数

  • 现在可以使用 NUnit 测试 EntryPoints 中的 DocMemo() 函数,如下所示:

    <TestFixture()> Public Class Numbering
    
    Private appWord As Word.Application
    Private objMacros As Object
    
    <TestFixtureSetUp()> Public Sub LaunchWord()
        appWord = New Word.Application
        appWord.Visible = True
    
        Dim AddIn As COMAddIn = Nothing
        Dim AddInUtilities As IAddInUtilities
        For Each tempAddin As COMAddIn In appWord.COMAddIns
            If tempAddin.Description = "CobbettsMacrosVsto" Then
                AddIn = tempAddin
            End If
        Next
        AddInUtilities = AddIn.Object
        objMacros = AddInUtilities.TestObject
    
    
    End Sub
    
    <Test()> Public Sub DocMemo()
    
    
        objMacros.DocMemo()
    End Sub
    
    <TestFixtureTearDown()> Public Sub TearDown()
        appWord.Quit(False)
    End Sub
    
    End Class
    

    您唯一无法进行单元测试的是实际的 Click 事件,因为您以不同的方式调用 EntryPoint,即通过 RequestComAddInAutomationService 接口(interface)而不是通过事件处理程序。

    但是它有效!

    关于vb.net - Microsoft Office .NET 插件的单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/126526/

    相关文章:

    Vb.Net 2D 字典 - 非常慢

    .net - 是否可以在 .net 中执行 "mixed"XML 序列化?

    vba - Google Apps 宏 - 与 Office VBA 宏相比如何?

    sharepoint - 如何通过 API 查找 OneDrive 是否对 Office365 中的用户有效?

    c# - 构建 Internet Explorer 扩展/附加组件?

    vb.net - 无法设置 Outlook.TaskItem 的 RTFBody 属性

    .net - 将图表添加到 WordprocessingML

    visual-studio - 我应该在 Visual Studio 加载项中的何处附加解决方案或项目事件?

    c# - Visual Studio 和加载项卸载

    vb.net - 如何仅设置 DateTime 的时间部分