用于Microsoft Office的.NET加载项的单元测试

Ric*_*den 6 vb.net add-in ms-office

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

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

现在,我可以使用Application.COMAddIns("addin的名称").对象接口来获取引用,但这会得到一个通过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(即时聊天reqMsg)在System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke (MessageData&msgData,Int32类型)

我尝试使主加载项COM可见并且错误更改:

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

虽然我有一个解决方法,它很混乱并且在实际项目中放置了大量测试代码而不是测试项目 - 这实际上并不是NUnit的工作方式.

Ric*_*den 3

我就是这样解决的。

  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
Run Code Online (Sandbox Code Playgroud)

在 ThisAddin 中,然后

Friend Sub DocMemo()
    OpenDocByNumber("Prec", 8862, 1)
End Sub
Run Code Online (Sandbox Code Playgroud)

在我的新 EntryPoints 文件中。

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

    公共接口 IAddInUtilities

#If DEBUG Then

Sub DocMemo()
Run Code Online (Sandbox Code Playgroud)

#End If

End Interface


Public Class AddInUtilities
    Implements IAddInUtilities
    Private Addin as ThisAddIn
Run Code Online (Sandbox Code Playgroud)

#If DEBUG Then

Public Sub DocMemo() Implements IAddInUtilities.DocMemo
    Addin.DocMemo()
End Sub
Run Code Online (Sandbox Code Playgroud)

#End If

 Friend Sub New(ByRef theAddin as ThisAddIn)
     Addin=theAddin
 End Sub
 End Class
Run Code Online (Sandbox Code Playgroud)
  1. 我转到 ThisAddIn 文件并添加

    私人公用事业作为 AddInUtilities

    受保护的覆盖函数 RequestComAddInAutomationService() As Object 如果公用程序什么都没有,则公用程序 = New AddInUtilities(Me) End If 返回公用程序 End Function

现在可以使用 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
Run Code Online (Sandbox Code Playgroud)

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

但它有效!