【问题标题】:Unit Testing of .NET Add-In for Microsoft OfficeMicrosoft Office .NET 插件的单元测试
【发布时间】:2008-09-24 11:09:22
【问题描述】:

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

问题是在 Office 应用程序(在我的例子中是 Word)中加载了一个 .NET 程序集,我需要一个对 .NET 程序集实例的引用。我不能只实例化该对象,因为它没有 Word 的实例来做事。

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

COM 对象(一个 VB.NET 类)实际上有一个对真正加载项实例的引用,但我尝试将它返回给 NUnit,却得到了一个不错的 p/Invoke 错误:

System.Runtime.Remoting.RemotingException :此远程代理没有通道接收器,这意味着服务器没有注册的服务器通道正在侦听,或者此应用程序没有合适的客户端通道与服务器通信。 在 System.Runtime.Remoting.Proxies.RemotingProxy.InternalInvoke(IMethodCallMessage reqMcmMsg,布尔值 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 真正的工作方式。

【问题讨论】:

    标签: vb.net ms-office add-in


    【解决方案1】:

    我就是这样解决的。

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

    2. 1234563这个文件。因此,例如,有一个函数可以打开一个标准文档并将“另存为”调用到我们的 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
    

    在我的新入口点文件中。

    1. 我添加了一个新的 AddInUtilities 文件,该文件具有

      公共接口 IAddInUtilities

    #If DEBUG Then

    Sub DocMemo()
    

    #End If

    End Interface
    
    
    Public Class AddInUtilities
        Implements IAddInUtilities
        Private Addin as ThisAddIn
    

    #If DEBUG Then

    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
    
    1. 我去 ThisAddIn 文件并添加

      作为 AddInUtilities 的私有实用程序

      Protected 覆盖函数 RequestComAddInAutomationService() 作为对象 如果实用程序什么都不是,那么 实用程序 = 新的 AddInUtilities(我) 万一 返回实用程序 结束函数

    现在可以使用 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 事件,因为您以不同的方式调用 EntryPoints,即通过 RequestComAddInAutomationService 接口而不是通过事件处理程序。

    但它有效!

    【讨论】:

      【解决方案2】:

      考虑使用各种模拟框架NMockRhinoMocks 等在您的测试中伪造 Office 的行为。

      【讨论】:

      • @RichardGadsden 是的,没错,我已经使用 NSubstitute 为 Excel 完成了它,最终并没有那么难。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-31
      • 2019-12-25
      • 1970-01-01
      • 1970-01-01
      • 2015-05-03
      • 1970-01-01
      • 2010-09-05
      相关资源
      最近更新 更多